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;
}

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

相关文章
|
程序员
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信(二)
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信(二)
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信(一)
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信
|
区块链
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信(三)
No.17 “迷茫的辍学大学生,我该如何找到自己的方向?”来自B站粉丝的求助信(三)
|
算法 C++
站在巨人的肩膀上,C++最常用的200个函数
站在巨人的肩膀上,C++最常用的200个函数
|
算法 C++ Python
昨晚学妹参加了B站秋招笔试,还想考考我?
昨晚学妹参加了B站秋招笔试,还想考考我?
109 0
|
存储 缓存 运维
站在巨人WordPress的肩膀上学架构
WordPress 可能是很多学习搭建云计算网站的第一课,写了篇 Hello World 就匆匆结束了对 WordPress 的体验。在全球前 1,000 万的网站中,三分之一都使用了 WordPress,像国外的白宫官网、纽约邮报、微软新闻中心、国内的爱范儿等等。因此开源社区的 WordPress 有着大量的开发者贡献代码和思路,帮助我们构建一个强大而成熟的网站。 我们要实现一个架构其实最重要的是三个目标,快、稳和省。 前端访问要快,后端运行要稳,但是实现前两者不能无节制的上升成本,我们要节省成本让利益最大化。。
1478 0
站在巨人WordPress的肩膀上学架构
|
6月前
|
视频直播
大咖与小白的日常:如何明目张胆地在老板面前摸鱼
上班时间抢红包、看帅哥视频?——不不不,老板,我只是在测试超低延时直播和体验高清。
|
弹性计算 SEO
SEO之大学生经验之谈
看过很多网站,觉得阿里云的SEO最合适大学生用来做课程网站设计。贵公司的云服务器有着比较快的访问速度,简单高效、安全可靠。
|
机器学习/深度学习 算法 前端开发
秋招上岸!双非本科,从外包实习到秋招收获阿里、美团、B站意向书!
大家好,我是路飞,今天这篇文章是来还愿的!秋招顺利结束,感谢大家一直以来的支持和陪伴!
秋招上岸!双非本科,从外包实习到秋招收获阿里、美团、B站意向书!
技术同学看过来,免费送你“第二套房”,还送“精装修”!
将您的原创技术博文同步(复制)到云栖社区 ,给你的博客再安一个家;只要您的技术博客3个月内有更新,申请同步后,即可获得相应奖励:1.     原创博文>=100篇,价值约300元的纪念奖励;2.     原创博文>=60篇<100篇,价值约200元的纪念奖励;3.     原创博文>=30篇<60.
8134 0