优秀开源库muduo阅读笔记

muduo阅读笔记

目录

  • 设计经验和思想
  • 服务端编程设计
  • std::bind 和 std::function (基于 closure闭包 的编程)
  • 参考资料

muduo开源库的笔记,比较杂,没有详细整理,现在就这么杂乱放着, 等真的需要再好好整理。

设计经验和思想

  1. 对象构造做到线程安全, 唯一的要求就是不要暴露this指针. 即不要在构造函数中注册任何回调; 也不要在构造函数中把this传给跨线程的对象; 即便在构造函数的最后一行也不行。 之所以这样规定,是因为在构造函数执行期间对象还没有完成初始化,如果this被泄露(escape)给了其他对象(其自身创建的子对象除外),那么别的线程有可能访问这个半成品对象,这会造成难以预料的后果。
  2. 对象析构的线程安全,一般通过shared_ptr, 因为shared_ptr不是线程安全,一般需要考虑额外加锁
  3. C++里可能出现的内存问题大致有这么几个方面: 1.缓冲区溢出(buffer overrun)。 2.空悬指针/野指针。 3.重复释放(double delete)。 4.内存泄漏(memory leak)。 5.不配对的new[]/delete。 6.内存碎片(memory fragmentation)。 正确使用智能指针能很轻易地解决前面5个问题,第6个问题需要明白内存碎片不可怕,可靠性只要不低于硬件和操作系统,普通PC故障率为3%-5%。 1.缓冲区溢出:用std::vector/std::string或自己编写Buffer class来管理缓冲区,自动记住用缓冲区的长度,并通过成员函数而不是裸指针来修改缓冲区。 2.空悬指针/野指针:用shared_ptr/weak_ptr,这正是本章的主题。 3.重复释放:用scoped_ptr,只在对象析构的时候释放一次。 4.内存泄漏:用scoped_ptr,对象析构的时候自动释放内存。 5.不配对的new[]/delete:把new[]统统替换为std::vector/scoped_array。
  4. 尽可能使用RAII(RAII包装锁和条件变量实现自动释放,多用STL,智能指针, RAII包装文件描述符等)
  5. 用流水线,生产者消费者,任务队列这些有规律的机制,最低限度地共享数据。这是我所知最好的多线程编程的建议了。
  6. 不要用读写锁(提高性能的错觉,大多数情况下与简单的mutex相比,性能实际降低了)和信号量 , 信号量的问题是没有所有权的概念
  7. 在多线程程序中,使用 signal的第一原则是不要使用 signal
  8. 进程间通信可以只用TCP,即适合单机也适合多机
  9. (计时)只使用gettimeofday(2)来获取当前时间。 ·(定时)只使用timerfd_*系列函数来处理定时任务。 gettimeofday(2)入选原因(这也是muduo::Timestamp class的主要设计考虑): 1.time(2)的精度太低,ftime(3)已被废弃;clock_gettime(2)精度最高,但是其系统调用的开销比gettimeofday(2)大。
  10. muduo日志库采用的是双缓冲( double buffering)技术,基本思路是准备两块 buffer: A和 B,前端负责往 buffer A填数据(日志消息),后端负责将 buffer B的数据写入文件。当 buffer A写满之后,交换 A和 B,让后端将 buffer A的数据写入文件,而前端则往 buffer B填入新的日志消息,如此往复。用两个 buffer的好处是在新建日志消息的时候不必等待磁盘文件操作,也避免每条新日志消息都触发(唤醒)后端日志线程。换言之,前端不是将一条条日志消息分别传送给后端,而是将多条日志消息拼成一个大的 buffer传送给后端,相当于批处理,减少了线程唤醒的频度,降低开销。另外,为了及时将日志消息写入文件,即便 buffer A未满,日志库也会每 3秒执行一次上述交换写入操作。 muduo异步日志的性能开销大约是前端每写一条日志消息耗时 1. 0 μ s ~ 1. 6 μ s。关键代码实际实现采用了四个缓冲区,这样可以进一步减少或避免日志前端的等待。
  11. 1.运行一个单线程的进程; 2.运行一个多线程的进程; 3.运行多个单线程的进程; 4.运行多个多线程的进程。这些模式之间的比较已经是老生常谈,简单地总结如下。·模式 1是不可伸缩的( scalable),不能发挥多核机器的计算能力。·模式 3是目前公认的主流模式。它有以下两种子模式:   3a  简单地把模式 1中的进程运行多份 16   3b  主进程 + woker进程,如果必须绑定到一个 TCP port,比如 httpd + fastcgi·模式 2是被很多人所鄙视的,认为多线程程序难写,而且与模式 3相比并没有什么优势。·模式 4更是千夫所指,它不但没有结合 2和 3的优点,反而汇聚了二者的缺点。本文主要想讨论的是模式 2和模式 3b的优劣,即:什么时候一个服务器程序应该是多线程的。从功能上讲,没有什么是多线程能做到而单线程做不到的,反之亦然,都是状态机嘛(我很高兴看到反例)。从性能上讲,无论是 IO bound还是 CPU bound的服务,多线程都没有什么优势。
  12. 我认为多线程的适用场景是:提高响应速度,让 IO和“计算”相互重叠,降低 latency。虽然多线程不能提高绝对性能,但能提高平均响应性能。一个程序要做成多线程的,大致要满足:·有多个 CPU可用。单核机器上多线程没有性能优势(但或许能简化并发业务逻辑的实现)。·线程间有共享数据ÿ

你可能感兴趣的:(网路编程,服务端编程,muduo)