面试高性能一般会问的几个问题
1.多进程和多线程的并发编程各自的优势
线程的进程在单核的芯片上都是可以进行运行的,这就涉及到了一个切片的概念,那么切片成本的不一样
多进程的好处就是地址空间相互独立,这是一个进程不影响另外一个进程,但是在进程之间的通信就比较困难;
内核态进行切换
2.协程为什么能够的实现更高的并发
协程为什么会更很快:切换速度较快,在用户态进行切换
非阻塞编程有关:所有的一套API可以有一个生态,全是使用的非阻塞
因为实现高并发,每一个链接都是需要占用内存的,只是占用十几k的内存
3.考的是CPU缓存(局部性原理)
-------第一种---------
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
cout<<st[i][j]<<endl;
-------第二种---------
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
cout<<st[j][i]<<endl;
首先理解二维数组的内存布局:二维数组按行进行布局
而当我们进行载入到缓存区(一级二级三级缓存)的时候
每次都是批量载入,所以按行访问比较好
4. 哈希表和二叉搜索树的优缺点
哈希表的缺点:遍历、范围查找是缺陷
二叉查找:树数据量比较大的话,树容易变得比较比较高-----所以数据库一般都使用b树
5. 哈希表有不同实现方式,也就是不同的解决方式。开散列(拉链法)和闭散列(顺序移址法或者二次哈希(一组哈希函数))。
拉链法:实现起来简单,另外一个复杂,
闭散列:闭散列容易实现持久化,对于大数据很有好处。
一个好的哈希函数:一个点,能够减少冲突--一般磨上一个质数。第二个点,一定能够计算速度够快,一般用移位操作。
扩容也是一个减少冲突的好方法---一般在哈希表都是进行动态扩容
7.自旋锁有什么特点,不适合用在什么场所
不适合用在代码执行比较慢的场所,因为自旋锁是忙等待,一直在访问那块区域。而一般互斥锁都是休眠等待。
自旋锁的实现,不是用轮询的方式,真实的自旋锁是利用poll等多路转接实现
一个代码是不是适合适用自旋锁,是看这段代码所执行时间,如果这段代码执行很快,那么自旋锁就比较适合。
8.如何防止读写锁的互相饿死?
利用一个优先级的安排即可;
9.怎样快速的将文件发给客户端?
传统的方法:
磁盘文件------(内核态)pagecache-------(用户态)用户缓冲区------(内核态)socket缓冲区-------网卡
拷贝 拷贝 拷贝 拷贝
切换 切换
------------------------------------------------------------------------以上用到了四个拷贝和切换
改进:
利用了零拷贝来解决—直接在内核态进行操作就可以了,减少拷贝和切换
10.相对于堆,为什么栈上分配对象的速度更快?
三个点:每一个线程都有一个独立的栈(独立的空间),linux每一个线程都分配了8M的栈,不用像堆一样会进行加锁。
栈上的内存是已经分配好了的,而堆还要申请和消除等一些系列的操作,缺点就是但是生命周期和大小有限