Skip to content

Amua/libgo

 
 

Repository files navigation

libgo

Build Status

libgo - 协程库、并行编程库

libgo是一个使用C++11编写的协作式调度的stackful协程库, 同时也是一个强大易用的并行编程库

目前支持三个平台:

Linux

MacOSX

Windows (Win7、Win8、Win10 x86 and x64 使用VS2013/2015编译) (要切换到windows分支)

使用libgo编写多线程程序,即可以像golang、erlang这些并发语言一样开发迅速且逻辑简洁,又有C++原生的性能优势,鱼和熊掌从此可以兼得。

libgo有以下特点:

  • 1.提供golang一般功能强大协程,基于corontine编写代码,可以以同步的方式编写简单的代码,同时获得异步的性能,

  • 2.支持海量协程, 创建100万个协程只需使用4.5GB物理内存.(真实值, 而不是刻意压缩stack得到的测试值)

  • 3.支持多线程调度协程, 提供高效的负载均衡策略和协程同步机制, 很容易编写高效的多线程程序.

  • 4.调度线程数支持动态伸缩, 不再有调度慢协程导致头部阻塞效应的问题.

  • 5.使用hook技术让链接进程序的同步的第三方库变为异步调用,大大提升其性能。再也不用担心某些DB官方不提供异步driver了,比如hiredis、mysqlclient这种客户端驱动可以直接使用,并且可以得到不输于异步driver的性能。

  • 6.动态链接和全静态链接均支持,便于使用C++11的用户静态链接生成可执行文件并部署至低版本的linux系统上。

  • 7.提供Channel, 协程锁(co_mutex), 协程读写锁(co_rwmutex), 定时器等特性, 帮助用户更加容易地编写程序.

  • 8.支持协程局部变量(CLS), 并且完全覆盖TLS的所有使用场景(详见教程代码sample13_cls.cpp).

  • 从近两年的用户反馈情况看,有很多用户都是已经有了一个异步非阻塞模型的项目(可能是基于epoll、libuv或asio等网络库),然后需要访问MySQL这类没有提供异步Driver的DB. 常规的连接池+线程池的方案在高并发场景下的开销十分昂贵(每个连接对应一个线程才能达到最佳性能, 几千个指令周期的线程上下文切换消耗+过多的活跃线程会导致OS的调度能力急剧下降), 让许多用户难以接受.

  • 鉴于此种情况, 想要使用libgo解决非阻塞模型中阻塞操作的问题,也是完全不必重构现有代码的, 全新的libgo3.0为此场景量身打造了三大利器, 可以无侵入地解决这个问题:运行环境隔离又可以便捷交互的多调度器(详见教程代码sample1_go.cpp),替代传统线程池方案的libgo协程池(详见教程代码sample10_co_pool.cpp),连接池(详见教程代码sample11_connection_pool.cpp)

  • tutorial目录下有很多教程代码,内含详细的使用说明,让用户可以循序渐进的学习libgo库的使用方法。

  • 如果你发现了任何bug、有好的建议、或使用上有不明之处,可以提交到issue,也可以直接联系作者: email: [email protected] QQ交流群: 296561497

libgo的编译与使用:

  • Vcpkg:

    如果你已经安装了vcpkg,可以直接使用vcpkg安装:

      $ vcpkg install libgo
    
  • Linux:

    1.使用CMake进行编译安装:

      $ mkdir build
      $ cd build
      $ cmake ..
      $ sudo make install
    
    如果希望编译可调试的版本, "cmake .." 命令执行完毕后执行:
    
      $ make debug
      $ sudo make install
    

    2.动态链接glibc: (libgo放到最前面链接)

      g++ -std=c++11 test.cpp -llibgo -ldl [-lother_libs]
    

    3.全静态链接: (libgo放到最前面链接)

      g++ -std=c++11 test.cpp -llibgo -Wl,--whole-archive -lstatic_hook -lc -Wl,--no-whole-archive [-lother_libs] -static
    
  • Windows: (目前windows只支持2.x版本,3.0的windows支持还要等一段时间)

    0.切换到windows分支

    1.使用git submodule update --init --recursive下载Hook子模块

    2.使用CMake构建工程文件.

      比如vs2015(x64):
      $ cmake .. -G"Visual Studio 14 2015 Win64"
    
      比如vs2015(x86):
      $ cmake .. -G"Visual Studio 14 2015"
      
      比如vs2013(x64):
      $ cmake .. -G"Visual Studio 12 2013 Win64"
    

    3.使用时需要添加两个include目录:src和src/windows, 或将这两个目录下的头文件拷贝出来使用

    4.如果想要执行测试代码, 需要依赖boost库. 且在cmake参数中设置BOOST_ROOT:

      	例如:
      	$ cmake .. -G"Visual Studio 14 2015 Win64" -DBOOST_ROOT="e:\\boost_1_61_0"
    

注意事项(WARNING):

    协程中尽量不要使用TLS, 或依赖于TLS实现的不可重入的库函数。
    如果不可避免地使用, 要注意在协程切换后要停止访问切换前产生的TLS数据。

可能产生协程切换的行为有以下几种:

* 用户调用co_yield主动让出cpu.
* 竞争协程锁、channel读写
* sleep系列的系统调用
* poll, select, epoll_wait这类等待事件触发的系统调用
* DNS相关系统调用(gethostbyname系列)
* 在阻塞式socket上的connect、accept、数据读写操作
* 在pipe上的数据读写操作

Linux系统上Hook的系统调用列表:

	connect   
	read      
	readv     
	recv      
	recvfrom  
	recvmsg   
	write     
	writev    
	send      
	sendto    
	sendmsg   
	poll      
	__poll
	select    
	accept    
	sleep     
	usleep    
	nanosleep
	gethostbyname                                                               
	gethostbyname2                                                              
	gethostbyname_r                                                             
	gethostbyname2_r                                                            
	gethostbyaddr                                                               
	gethostbyaddr_r

以上系统调用都是可能阻塞的系统调用, 在协程中使用均不再阻塞整个线程, 阻塞等待期间CPU可以切换到其他协程执行.
在原生线程中执行的被HOOK的系统调用, 与原系统调用的行为保持100%一致, 不会有任何改变.
  •   socket
      socketpair
      pipe
      pipe2
      close     
      __close
      fcntl     
      ioctl     
      getsockopt
      setsockopt
      dup       
      dup2      
      dup3      
    

    以上系统调用不会造成阻塞, 虽然也被Hook, 但并不会完全改变其行为, 仅用于跟踪socket的选项和状态.

Windows系统上Hook的系统调用列表:

	ioctlsocket                                                                        
	WSAIoctl                                                                           
	select                                                                             
	connect                                                                            
	WSAConnect                                                                         
	accept                                                                             
	WSAAccept                                                                          
	WSARecv                                                                            
	recv                                                                               
	recvfrom                                                                           
	WSARecvFrom                                                                        
	WSARecvMsg                                                                         
	WSASend                                                                            
	send                                                                               
	sendto                                                                             
	WSASendTo                                                                          
	WSASendMsg

About

Go-style concurrency in C++11

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 92.9%
  • CMake 3.3%
  • C 2.3%
  • Other 1.5%