4/1 背刺!春招B站一面,这些问题你都会吗?

简介: 4/1 背刺!春招B站一面,这些问题你都会吗?

下面我将分享一位同学在Bilibili一面的面试经历,对于这次面试,他的评价是,「很有难度」,你试试呢?

【提醒】通过这次面试经验,你将可以复习到以下知识点,注意汇总,不超过10个


  1. RPC调用的网络中断处理
  2. DPDK
  3. C++的多态实现和应用场景
  4. C++类的大小及成员变量初始化
  5. unique_ptr的用法
  6. Golang的内存分配器
  7. 项目的压力测试方法
  8. CPU负载过高的排查方法
  9. HTTP2.0和HTTP3.0的优势
  10. 进程、线程、协程的区别
  11. 内存分配大小的限制
  12. STL Vector的线程安全问题
  13. C++的内存序
  14. 算法题:k个一组反转链表

e7c98c16527500506b450f4b003ecc99.jpg

img

「面试官」: 你好,我们先从你的项目开始谈起。项目中RPC调用在网络中断后,作为client端的状态应该是怎么样的?


「求职者」: 网络中断后,客户端在发起RPC调用时会因为不能建立连接而失败。这时候,一般会有重试机制,例如重试一定次数或者在一定时间内重试。如果重试都失败的话,那么这次RPC调用就会报错。


「面试官」: 明白了。那你对DPDK有了解吗?


「求职者」: DPDK,全称Data Plane Development Kit,是英特尔开源的一套数据平面开发套件。它主要用于网络数据包的高速处理,可以绕过操作系统内核,直接在用户态处理网络数据包,避免了内核态和用户态之间的切换开销,提高了数据包处理的效率。


「面试官」: 很好。接下来,谈谈「C++多态」的实现,以及它的应用场景。


「求职者」: C++的多态主要是「通过虚函数和继承」来实现的。在基类中定义虚函数,然后在派生类中重写这个虚函数,通过基类的指针或引用来调用这个虚函数,就可以实现多态。多态的主要应用场景是当我们需要处理一组对象,这组对象都是同一个基类的派生类,但是具体是哪个派生类在编译时并不确定。这时候,我们就可以利用多态,将这组对象都当作基类对象来处理,而具体的行为会根据对象的实际类型来确定。


「面试官」: 那你知道一个空类的大小是多少吗?


「求职者」: 在C++中,一个空类的大小不是0,而是1字节。「这是为了保证两个不同的对象有不同的地址」。


「面试官」: 好的。那么,如果在class里面定义了int a,但是没有实现构造函数,实例化这个类后,a的值是什么?


「求职者」: 如果没有实现构造函数,那么a的值是未定义的,也就是说,它的值是随机的,取决于这块内存之前的状态。


「面试官」: 明白了。接下来,你能告诉我unique_ptr可以作为函数返回值吗?


「求职者」: 是的,unique_ptr可以作为函数返回值。因为C++11支持移动语义,所以在返回时,unique_ptr会被移动,而不是复制。这样就避免了资源的泄漏。


「面试官」: 那你对golang的内存分配器有了解吗?


「求职者」: golang的内存分配器是基于tcmalloc实现的,它将内存分为小对象和大对象两种。小对象使用fix-size的内存池,大对象使用页堆。golang的内存分配器还有一些特性,比如支持并发分配,支持分代回收等。


「面试官」: 了解了。那么,你的项目的压力测试是怎么做的?


「求职者」: 我们的压力测试是使用JMeter来进行的。「JMeter可以模拟大量用户并发访问」,我们会设置不同的并发数和请求频率,然后观察系统的响应时间、吞吐量、错误率等指标,以此来评估系统的性能。


「面试官」: 那如果项目中的CPU负载过高,你会怎么排查呢?


「求职者」: CPU负载过高,「首先我会使用top或者htop命令来查看CPU的使用情况」,看看是哪个进程占用的CPU最高。然后,我会使用perf或者gprof这样的性能分析工具,对这个进程进行性能分析,找出CPU使用高的函数。接下来,我会深入到这个函数的代码中,看看是否有可以优化的地方。如果这个函数是一个循环或者递归,我会检查是否有冗余的计算,是否可以通过缓存结果来减少计算量。如果这个函数是一个阻塞操作,我会看看是否可以通过异步或者并发来提高效率。


「面试官」: 很好。那么,你的项目的瓶颈在哪个Server上呢?


「求职者」: 我们的项目的「瓶颈主要在数据库服务器上」。因为我们的业务逻辑比较复杂,涉及到大量的数据库操作,而且有些查询非常复杂,导致数据库的响应时间较长。所以,我们现在正考虑对数据库进行优化,比如使用索引来提高查询速度,使用读写分离来提高并发性能,或者使用分片来分散数据库的压力。


「面试官」: 明白了。接下来,我想问一下,快手直播流媒体是走长连接网关推送的吗?


「求职者」: 一般的流媒体服务,比如直播,是需要维持一个长连接的,这样才能保证实时性。至于是否通过网关推送,我想应该是的,因为通过网关可以进行负载均衡,提高系统的可用性。


「面试官」: 好的。那你能讲一下HTTP3.0对比HTTP 2.0的优势吗?


「求职者」: HTTP3.0的最大优势是引入了QUIC协议,替代了TCP协议。QUIC协议解决了TCP的头阻塞问题,实现了全双工的多路复用。此外,QUIC协议还支持0-RTT的快速握手,提高了连接的建立速度。而且,QUIC协议还实现了更好的拥塞控制和丢包恢复。


「面试官」: 明白了。那HTTP 2.0 对比 HTTP 1.1的优势又是什么呢?


「求职者」: HTTP 2.0的主要优势是实现了多路复用,解决了HTTP 1.1的头阻塞问题。此外,HTTP 2.0还引入了服务器推送和首部压缩等特性,进一步提高了效率。


「面试官」: 很好。接下来,讲一下进程、线程、协程的区别。


「求职者」: 进程是操作系统进行资源分配的最小单位,线程是操作系统进行调度的最小单位。每个进程有自己独立的地址空间和系统资源,而线程则共享所属进程的资源。协程又称为轻量级线程,它是一种用户态的线程,不需要操作系统参与调度,完全由程序自己控制,因此开销更小,切换更快。


「面试官」: 好的。一个进程调用malloc最大能分配多大的内存?


「求职者」: 一个进程调用malloc能分配的最大内存主要取决于操作系统的位数和进程的地址空间。例如,在32位操作系统中,理论上最大可以分配4GB的内存,但实际上会小于这个值,因为操作系统还需要一部分地址空间来管理硬件和操作系统自身。在64位操作系统中,理论上可以分配的内存会更大,但实际可用内存还是要受到物理内存和操作系统限制。


「面试官」: 明白了。如果有一个8G物理内存的机器,调用malloc(10G)会发生什么?


「求职者」: 如果在一个只有8G物理内存的机器上尝试分配10G内存,操作系统会使用虚拟内存来满足这个请求。虚拟内存通常使用硬盘作为额外的存储空间。但是,如果硬盘的交换空间(swap space)不足,malloc调用可能会失败,并返回NULL指针。


「面试官」: 好的,来谈谈STL Vector线程安全吗,不安全在哪?


「求职者」: STL Vector本身不是线程安全的。如果有多个线程同时对同一个Vector对象进行操作,比如一个线程正在添加元素,而另一个线程正在删除元素或迭代元素,那么就可能会导致数据竞争和不可预期的行为。


「面试官」: 那在多线程下使用Vector一定要加锁吗?


「求职者」: 是的,如果在多线程环境中使用Vector,为了保证操作的原子性和数据的一致性,通常需要对Vector的操作加锁。


「面试官」: 如果两个线程同时对Vector下相同索引的元素进行修改会发生什么?


「求职者」: 如果两个线程同时对Vector下相同索引的元素进行修改,那么最终的结果取决于哪个线程最后完成写入操作。这是典型的竞态条件,可能会导致程序的行为难以预测和调试。


「面试官」: 那么,能介绍一下C++的内存序吗?


「求职者」: C中的内存序是指在多线程环境下,对内存的读写操作的可见性和顺序。在多处理器系统中,不同处理器对内存的读写操作可能会有不同的顺序,这就导致了内存顺序问题。为了解决这个问题,C11引入了原子操作和内存序的概念,提供了几种不同的内存序选项,例如

memory_order_relaxedmemory_order_consumememory_order_acquirememory_order_releasememory_order_acq_relmemory_order_seq_cst

「面试官」: 最后一个问题,手撕:k个一组反转链表。

「求职者」: 好的,这个问题可以通过迭代或递归来解决。我可以给出一个迭代的解法。

ListNode* reverseKGroup(ListNode* head, int k) {
    if(head == nullptr || k == 1) return head;

    ListNode dummy(0);
    dummy.next = head;
    ListNode *curr = &dummy, *nex, *pre = &dummy;

    int count = 0;
    while(curr->next != nullptr) {
        curr = curr->next;
        count++;
    }
    
    while(count >= k) {
        curr = pre->next;
        nex = curr->next;
        for(int i = 1; i < k; i++) {
            curr->next = nex->next;
            nex->next = pre->next;
            pre->next = nex;
            nex = curr->next;
        }
        pre = curr;
        count -= k;
    }
    
    return dummy.next;
}

「面试官」: 很好,你的回答很全面。谢谢你,这就结束了我们今天的面试,等消息吧。

相关文章
|
3月前
|
存储 缓存 JavaScript
最全前端面试总结来袭!抓紧收藏了!
最全前端面试总结来袭!抓紧收藏了!
|
3月前
|
缓存 负载均衡 前端开发
【前端实习生备战秋招】—前端性能优化篇,建议收藏
【前端实习生备战秋招】—前端性能优化篇,建议收藏
|
算法 C++ Python
昨晚学妹参加了B站秋招笔试,还想考考我?
昨晚学妹参加了B站秋招笔试,还想考考我?
|
架构师
送上9个免费设计源泉,轻松拿捏网站“氛围感”
送上9个免费设计源泉,轻松拿捏网站“氛围感”
207 0
送上9个免费设计源泉,轻松拿捏网站“氛围感”
|
存储 缓存 运维
站在巨人WordPress的肩膀上学架构
WordPress 可能是很多学习搭建云计算网站的第一课,写了篇 Hello World 就匆匆结束了对 WordPress 的体验。在全球前 1,000 万的网站中,三分之一都使用了 WordPress,像国外的白宫官网、纽约邮报、微软新闻中心、国内的爱范儿等等。因此开源社区的 WordPress 有着大量的开发者贡献代码和思路,帮助我们构建一个强大而成熟的网站。 我们要实现一个架构其实最重要的是三个目标,快、稳和省。 前端访问要快,后端运行要稳,但是实现前两者不能无节制的上升成本,我们要节省成本让利益最大化。。
1439 0
站在巨人WordPress的肩膀上学架构
|
消息中间件 分布式计算 负载均衡
阿里技术面全A,终面却被产品经理拉下马,我不服
阿里技术面全A,终面却被产品经理拉下马,我不服
阿里技术面全A,终面却被产品经理拉下马,我不服
|
机器学习/深度学习 算法 前端开发
秋招上岸!双非本科,从外包实习到秋招收获阿里、美团、B站意向书!
大家好,我是路飞,今天这篇文章是来还愿的!秋招顺利结束,感谢大家一直以来的支持和陪伴!
秋招上岸!双非本科,从外包实习到秋招收获阿里、美团、B站意向书!
|
消息中间件 算法 前端开发
双非本科22届暑期实习,成功拿到B站、阿里实习offer
拼一把不一定成功,但是不试试看肯定没有结果!
双非本科22届暑期实习,成功拿到B站、阿里实习offer
阿里研究型实习生体验
经过两年研究时间,找到了学校的教职, 也找到了老婆, 感谢阿里~