本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点
序列化
判断标准
- 序列化后的码流大小
- 性能
- 跨语言
Serializable方式
- 码流偏大
- 性能较低
XML方式
- 人机可读性好
- 文件格式复杂、占带宽
JSON
- 轻量级、兼容性好、格式简单,人机可读性较好
- 可读性没有XML好,额外空间消耗比较大
ProtoBuff
如何让单机的应用程序支持几十万至百万级别的长连接?
- 首先要突破系统对应用进程的线程数限制:ulimit -n 1000000
- 还要突破软限制和硬限制:cat /etc/security/limits.conf;改完以后还要该so,让系统重新加载这个文件
- 操作系统的限制,所有进程的文件连接数的限制
- socket通信时,每个socket都有2个缓冲区,一般是4K*2,连接数过大,内存就会很高,就需要把这个缓冲区调小一点:SO_SNDBUF;SO_RCVBUF
select、poll、epoll的区别?
- 都是操作系统实现的IO多路复用的机制
- select是操作系统都支持的,poll和epoll主要是在类UNiX的操作系统中支持
- 支持一个进程所能打开的连接数限制不一样:selector是1024个(64位上面可以变成2048);poll和select没有太大区别,不过连接上select是用数组来维护,poll是链表维护,最大连接数上poll是没限制的;epoll没有什么限制,只受限于机器内存的大小
- 连接数激增时的效率不同:当连接数上升到几十万百万的时候,select和poll性能会急剧下降,而epoll跟总连接数没有关系,只能活跃的连接有关,性能基本不变
- 消息的传递方式:select和poll在每次消息调用中都需要将很多数据从用户空间拷贝到内核空间;epoll不需要(共享一块内存)
- 怎么选择?:连接数比较少又比较活跃的时候,select和poll可能性能更好
- select、poll只支持水平触发,epoll默认是水平触发,也支持边缘触发
水平触发(LT)和边缘触发(ET)?
水平触发:socket的接收缓冲区里有数据来了,只要缓冲里有数据,select、poll或者epoll就都会一直收到通知
边缘触发:只有在有新数据到达socket的缓冲区时才会触发
直接内存比堆内存快在哪里?
直接内存避免了二次拷贝,如果buffer在堆上,就需要先从堆拷贝到应用进程缓冲区,再从应用进程缓冲区拷贝到内核套接字缓冲区,再发送到网络,直接内存少了从堆拷贝到应用进程的这一步。
数据从应用进程缓冲区拷贝到套接字发送缓冲区时,内存是不允许发生变化的,不能失效的
什么是零拷贝
指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。
DMA:direct memory access,用于接收CPU的指令负责去IO拷贝。会把文件数据拷贝到内核缓冲区,再拷贝到用户空间
零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而提高数据传输效率
传统数据传送过程
磁盘 -->DMA拷贝到内核文件读取缓冲区 -->CPU拷贝到应用进程缓冲区 --> CPU拷贝到套接字发送缓冲区(应用进程到内核进程) --> DMA拷贝到网络设备(网卡)
4次拷贝,4次上下文切换
内存映射:MMAP
把文件映射到应用进程的某段内存区域里面,减少CPU拷贝到应用进程的步骤
Linux之sendfile
DMA将文件拷贝到文件读取缓冲区后,直接进行CPU拷贝到套接字发送缓冲区,都在内核空间中,省去了从应用进程周转的拷贝
3(2)次拷贝2次上下文切换
Linux之slice
在上面的基础上,文件缓冲区和套接字缓冲区之间用了管道机制PIPE,管道实际上就是共用了一段内存
2次拷贝,2次上下文切换
Java JDK里面的零拷贝主要是MMAP和sendfile,sendfile比如FileChannel的transferFrom
欢迎关注我的公众号查看更多精彩文章!