首先要声明,这些比较只适合于在写代码的时候作为所谓的 rule of thumb 采用,任何严肃的性能测试都需要在实际应用中结合真实世界的数据进行评测。
简单评测几个在日志库中要用到的操作的性能,大致比例是这样:
malloc 256字节 : 30
memcpy 256字节 : 1
lock_guard : 4
write 256字节 : 120
writev 2*256字节 : 60
其中最后一个是每次写两个256字节的块,循环次数减半,也就是说,写的总数据量相同。
重申一次结论:
1. 动态内存分配比较昂贵,远远贵过memcpy
2. mutex lock还算不错,所以不要太怕用它
3. 写磁盘虽然昂贵,但还不算太糟,主要开销事实上是系统调用本身,合并块读写能减少系统调用数量,根据这个进行优化是值得的
另一个发现就是,即便只写一个块,writev 还是比 write 稍稍快一点,所以只要有 writev,就用 writev。
还要记录一下一个工作中得到的经验,在一台2011年中比较典型的台式机上,Linux 进程切换的代价:
如果没有 cache miss :大约 2 - 3 微秒
如果有 cache miss :大约 30 微秒
而线程切换的代价,事实上跟进程切换比较相近,这是在我的工作中得到的感觉。
在这方面,教训是:
1. Cache miss 相对非常昂贵,比起在 cache 中执行,大约能慢上两个数量级
2. 如果想要最小化线程切换的代价,考虑把进程放到一个 CPU 核上,例如用 Linux 的 taskset 命令
3. 线程切换,至少在 Linux 下,还是有一定代价的。
4. 用户态到内核态的切换,还算是比较高效的的,在100个纳秒左右(当然这个没包含 cache miss 的代价吧?)