正文
计算机底层的秘密读书笔记之一
摘要
上周天在家休息时在知乎上面看到了影响性能的几个场景.
里面见到了cache的乒乓问题,以及cache line的伪共享问题.
知乎的答案里面图文并茂. 作者的思路也很清晰
就顺着水印找到了公众号还有作者刚出版的一本书.
京东周一快递到手后,这几天晚上都没陪儿子跳绳一直在抽时间来看.
感觉收获很多, 特意想总结一下, 希望能够备忘和提高自己.
书的文章结构
第一章: 编程语言到可执行程序
第二章: 程序运行起来的情形
第三章: 内存的介绍
第四章: 最重要的CPU
第五章: CPU里面重要的Cache
第六章: I/O
用自己的理解改写了下章节.
不像原书这样华丽,为了好记.
学习到的重要的点-1
词法分析和语义分析
文本型的程序源文件,经过词法分析, 语义分析,转换成语法树.
高级语言的发展, 解释性语言,以及编译器的来源与用途.
代码中都有一个连接操作, 其实java的类加载器里面也有连接的一个过程.
连接就有静态连接和动态连接.
各有他的优缺点. 为了可移植性. 静态连接更好一些. (比如编译安装redis)
为了节省磁盘和内存 动态连接更优秀一些
静态连接不仅会增加磁盘的用量. 加载到内存之后text的段区域会占用更多的内存空间.
本周其实还看到了一个公众号讲解CPU的里面说到.
微观来看 性能其实是:
时间/程序 的倒数.
又等于 单位时间执行的指令数 与 程序内包含的指令数的除法关系.
学习到的重要的点-2
进程-线程-协程
现代操作系统其实可以理解为是一个时分复用的操作系统.
摩尔定律逐渐失效的这几年, 增加了多核心多进程多路来提高绝对性能.
最开始的计算机科学主要是基于 单核心单线程的 机器来考虑.
所以其实很多书本上的知识网络上的知识都是不太合适的.
一般的说法是 进程是操作系统进行资源分配的最小单元.
线程是操作系统进行调度的最小单元.
进程之间的资源是隔离的. 线程之间可以共享同一个进程内的大部分上下文信息.
进程切换时需要切换很多内容. 上下文,所有寄存器的状态 TLB, 中断等等.
context switch 是一个很重的操作. 需要上千个指令周期才可以完成.
为了减少进程上下文切换的性能损耗.
计算机科学增加了线程的概念 线程可能仅需要切换几个寄存器就可以了. 不需要全部进行上下文切换.
并且有了线程的概念之后就有了 线程池的概念
因为任何资源的create 和 destory 都需要耗费资源和时间. 很多任务其实执行很快
减少这一部分的overhead 能够极大的减少程序运行的时间减少CPU的使用.
联想到自己使用最多的jvm调优这一块.
栈区里面的栈帧 就是对应不同的线程.
堆区里面是所有的线程栈共享的区域.
所以并发变成里面最关键的就是 堆区共享资源的隔离与使用.
这也是为JVM有一个逃逸分析后栈上分配的性能要远大于堆上分配.
其实都是内存, allocation的时间是一样的. 但是堆区有很多进行类似于MESI判断的额外开销
但是栈上都是私有的, 不需要做检查和设置, 性能就要快的多, 并且内存分配都是线性的, 比对上需要使用GC等要快速的多.
有了多线程有了共享, 线程并发的安全就是最大需要考量的地方.
Threadlocal 就是一个核心解决方案.
但是线程池的存在导致ThreadLocal在线程被get和dispose时需要专门进行一下 clean 不然会出现不可控的权限数据逃逸.
关于协程的概念
其实协程就是应用程序自己实现了部分线程调度的处理
不管进程和线程, 其实都有跟内核线程的一个对象关系.
但是协程其实是应用程序自己进行管理和调度的. 能够避免线程的部分寄存器的切换性能损耗
但是对应的, 需要更加注意并发的安全.
其实大数据的map reduce 也是类似于协程的里面.将不相关的部分应用层切分. 这样就可以最大化的避免因为共享导致的资源损耗.
学习到的重要的点-3
同步 异步 阻塞 非阻塞
事件循环与事件驱动
这一章的内容其实与最后的IO很贴近了
但是我一直理解的不是很对.
异步就是不等待结果
同步就是必须等待
同步异步调用方主动的行为
阻塞和非阻塞是被动的行为.
阻塞的应用 其实就是没办法运行了. 异步和非阻塞是可以进行进行下一步的操作.
CPU的性能提升.离不开乱序,超标量流水线等技术.
其实这些技术的实现才保证了异步 非阻塞的方式可以快速的进行性能调优
epoll等可以一等后面进行总结.