baidu / sofa-pbrpc

A light-weight RPC implement of google protobuf RPC framework.
Other
2.13k stars 655 forks source link

无锁优化 #114

Closed CaesarTang closed 8 years ago

CaesarTang commented 8 years ago

Hi, 在sofa源码中看到大量使用锁的地方,部分地方如果实现成无锁是不是可以将性能提升的更高一些。 如以下可以两处是不是可以这样优化: 1、RpcClientImpl::FindOrCreateStream中存在_stream_map的find与insert,这个地方加了锁以防止多线程读写core,_stream_map会在请求级不停的加锁解锁,是否可以将_stream_map的初始化实现到RpcClientImpl的初始化,此处只find不insert,这样可以不加锁。 代码:https://github.com/baidu/sofa-pbrpc/blob/master/src/sofa/pbrpc/rpc_client_impl.cc#L372 2、代码中使用std::deque的地方也使用了锁以保证多线程安全,是否可以使用boost::lockfree::queue无锁队列替换以减少锁的使用呢?这样是不是可以提高一些性能? 如:https://github.com/baidu/sofa-pbrpc/blob/master/src/sofa/pbrpc/rpc_message_stream.h#L368

以上是阅读源码时的疑问以及自己的想法,如有不对望请指正。

cyshi commented 8 years ago

Hi

  1. stream_map 在RPC中负责管理连接,不仅涉及读操作,还有写操作,例如清理连接时,这个锁主要是在client中,对性能要求比较高的话,可以使用多个RpcClient,不过这块我们也在优化中
  2. 应用程序的性能,不能仅仅从加锁的角度去看,个人认为有两个方面
    • 锁的竞争程度

实际上在锁竞争激烈的情况下,无锁代码性能往往要低于有锁,因为无锁的实现通常是用CAS操作,竞争激烈的话往往浪费大量cpu。另外无锁代码通常需要考虑的更多,内存泄露,ABA问题等等,也会造成一些开销。

我们在做RPC的性能优化时,实际测试过,替换成boost::lockfree::queue对性能基本没有帮助,因此舍弃了这个更新。

这部分如果想优化的话,个人认为可以从线程模型下手,每线程一个无锁的SPSC队列,这样的性能可能会更好

pbrpc在这方面实际已经做了大量工作,包括从_pending_calls中拆出_swapped_calls等,来控制临界区大小,所以实际测试中lockfree::queue的作用并不大

最后,还是要感谢对pbrpc提出的建议,欢迎贡献代码 :)

CaesarTang commented 8 years ago

非常感谢 @cyshi 的回答,解答我的不少疑问。我也是在看代码中对这些地方感到疑惑,不知道sofa团队已经在这方面做了测试。本人在pbrpc上学习的尚浅,对一些知识(锁,无锁队列实现原理)的认识比较片面,也没有做过深度尝试,希望以后可以向各位多学习,争取早日有能力贡献代码 :)