libgo

C++11 中的 Go 风格并发。(Go-style concurrency in C++11)

Github stars Tracking Chart

libgo

libgo -- 一个协程库和一个并行编程库。

Libgo 是一个用 C++11 编写的用于协作调度的堆栈协程库,它还是一个功能强大且易于使用的并行编程库。

当前支持三种平台:

  • Linux
  • Mac OSX
  • Windows(Win7 以上版本,x86 或 x64,符合 VS2015/2017)

使用 libgo 编写多线程程序,它可以像 golang 和 Erlang 并发语言一样快速和逻辑地开发,并具有 C++ 本机的性能优势,它使得人们可以事奉上帝和财神。

特性

Libgo 具有以下特征:

  • 1、提供 golang 通用的强大协议,基于协程编写代码,可以同步方式编写简单代码,同时实现异步性能。
  • 2、支持大量的协程,创建 100万 个协程仅需要 4.5 GB 物理内存。 (来自真实测试的数据,没有故意压缩的堆栈情况。)
  • 3、支持多线程调度协议,提供高效的负载均衡策略和同步机制,易于编写高效的多线程程序。
  • 4、调度线程数支持动态扩展,不会因调度慢而造成头部阻塞。
  • 5、使用挂钩技术使链接过程的同步第三方库成为异步调用,从而大大提高了它们的性能。不必担心某些数据库管理机构不提供异步驱动程序,例如 hiredis 和 mysqlclient,它们是可以直接使用并且可以实现与异步驱动程序相当的性能的客户端驱动程序。
  • 6、动态链接和完全静态链接均受支持,这使得使用 C++11 静态链接轻松生成可执行文件并将其部署到低级 Linux 系统很容易。
  • 7、提供 Channel、Co_mutex、Co_rwmutex、计时器等功能,以帮助用户更轻松地编写程序。
  • 8、支持该过程的局部变量(CLS),并完全涵盖 TLS 的所有方案(有关详细信息,请阅读教程代码 sample13_cls.cpp)。
  • 根据过去两年的用户反馈,许多开发人员都有一个具有异步非阻塞模型的项目(可能基于 epoll、libuv 或 ASIO 网络库),然后需要访问不提供异步驱动程序的数据库(如 MySQL)。在高并发情况下,传统的连接池和线程池方案非常密集(每个连接必须对应一个线程才能获得最佳性能。线程上下文切换的成千上万个指令周期非常密集,并且活动线程过多会导致 OS 性能急剧下降。调度能力,这是许多开发所不能接受的。
  • 在这种情况下,如果我们想使用 libgo 解决非阻塞模型中的阻塞操作问题,就不需要重构现有代码。新的 libgo 3.0 为这个场景创建了三个特殊工具,它们可以在没有干扰的情况下解决此问题:具有独立运行环境且易于交互的多调度程序(有关详细信息,请阅读教程代码 sample1_go.cpp),libggo 可以代替传统线程池方案。 (有关详细信息,请阅读教程代码 sample10_co_pool.cpp 和 sample11_connection_pool.cpp)
  • **教程目录包含许多教程代码,包括详细说明,以便开发人员可以逐步学习libgo库。 **
  • 如果发现任何错误,好的建议或使用歧义,则可以提交问题或直接与作者联系:电子邮件:289633152@qq.com

编译与使用

编译并使用 libgo:

  • Vcpkg:

如果已安装 vcpkg,则可以直接使用 vcpkg 进行安装:

$ vcpkg install libgo

  • Linux:

1.使用 cmake 编译安装:

 $ mkdir build
  $ cd build
  $ cmake ..

$ make debug #如果您不需要可调试的版本,请跳过它。 $ sudo make uninstall $ sudo make install
</p>
<p>2.动态链接到 glibc:(将 libgo 放在链接列表的最前面)

</p>
<pre> 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 -lpthread -Wl,--no-whole-archive [-lother_libs] -static
  • Windows:(3.0 与 Windows 兼容,直接使用 master 分支即可!)

0.使用 GitHub 在 Windows 上下载代码时,必须注意换行符的问题。 请正确安装 git(使用默认选项)并使用 git clone 下载源代码。 (请勿下载压缩包)

1.使用CMake构建项目。

 #For example vs2015(x64):
  $ cmake .. -G"Visual Studio 14 2015 Win64"

  #For example vs2015(x86):
  $ cmake .. -G"Visual Studio 14 2015"

2.如果要执行测试代码,请链接 boost 库。 并在 cmake 参数中设置 BOOST_ROOT:

For example:
      $ cmake .. -G"Visual Studio 14 2015 Win64" -DBOOST_ROOT="e:\\boost_1_69_0"

注意事项(警告):

应尽可能避免依赖 TLS 实现的 TLS 或非可重入库函数。 如果不可避免,则在进程切换后,应注意停止访问切换前生成的 TLS 数据。

有几种行为可能导致进程切换:

  • 用户调用 co_yield 主动放弃 cpu 跨度。
  • 竞争性合作锁,频道读取和写入。
  • 睡眠系列的系统调用。
  • 等待事件触发的系统调用,例如 poll、select、epoll_wait。
  • 与 DNS 相关的系统调用(gethostbyname 系列)。
  • 在阻塞套接字上进行 connect、accept、数据读写操作。
  • 管道上的数据读写操作。

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,但不会引起阻塞,但不会完全更改其行为,仅用于跟踪套接字选项和状态。

Windows系统上的挂钩系统调用列表:

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

(The first version translated by vz on 2020.07.26)

Main metrics

Overview
Name With Owneryyzybb537/libgo
Primary LanguageC++
Program languageCMake (Language Count: 6)
PlatformLinux, Mac, Windows
License:MIT License
所有者活动
Created At2015-12-24 03:20:41
Pushed At2023-07-03 03:31:22
Last Commit At2023-03-10 10:33:42
Release Count13
Last Release Namev3.1-stable (Posted on )
First Release Namev1.0 (Posted on )
用户参与
Stargazers Count3.3k
Watchers Count211
Fork Count762
Commits Count576
Has Issues Enabled
Issues Count266
Issue Open Count111
Pull Requests Count22
Pull Requests Open Count10
Pull Requests Close Count14
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

libgo

Build Status

libgo -- a coroutine library and a parallel Programming Library

Libgo is a stackful coroutine library for collaborative scheduling written in C++ 11, and it is also a powerful and easy-to-use parallel programming library.

Three platforms are currently supported:

Linux

MacOSX

Windows (Win7 or above,x86 or x64,complie with VS2015/2017)

Using libgo to write multi-threaded programs, it can be developed as fast and logical as golang and Erlang concurrent languages, and has the performance advantages of C++ native.It make it happen that one can serve God and Mammon.

Libgo has the following characteristics:

  • 1.Provide golang's General powerful protocol, write code based on coroutine, can write simple code in a synchronous manner, while achieving asynchronous performance.

  • 2.Supporting massive coroutines, creating 1 million coroutines requires only 4.5 GB of physical memory. (data from real test, in no deliberately compressed stack situation.)

  • 3.Supporting multi-threaded scheduling protocols, providing efficient load balancing strategy and synchronization mechanism, it is easy to write efficient multi-threaded programs.

  • 4.The number of scheduled threads supports dynamic scaling, and there is no head blocking caused by slow scheduling.

  • 5.Use hook technology to make synchronous third-party libraries of linking processes become asynchronous calls, which greatly improves their performance. There's no need to worry that some DB authorities don't provide asynchronous drivers, such as hiredis and mysqlclient, which are client drivers that can be used directly and can achieve performance comparable to that of asynchronous drivers.

  • 6.Both dynamic links and full static links are supported, which makes it easy to generate executable files using C++ 11 static links and deploy them to low-level Linux systems.

  • 7.Provide Channel, Co_mutex, Co_rwmutex, timer and other features to help users write programs more easily.

  • 8.Supports local variables (CLS) of the process, and completely covers all scenarios of TLS (read the tutorial code sample13_cls.cpp for details).

  • From user feedback in the past two years, many developers have a project with an asynchronous non-blocking model (probably based on epoll, libuv or ASIO network libraries) and then need access to DBs such as MySQL that do not provide asynchronous driver. Conventional connection pool and thread pool schemes are intensive in high concurrency scenarios (each connection have to correspond to a thread for Best performance. Thousands of instruction cycles of thread context switching are intensive and too many active threads will lead to a sharp decline performance in OS scheduling capacity, which is unacceptable to many develops.

  • In this situation, there is no need to reconstruct the existing code if we want to use libgo to solve the problem of blocking operation in non-blocking model. The new libgo 3.0 has created three special tools for this scenario, which can solve this problem without intrusion: multi-scheduler with isolated running environment and easy interaction (read the tutorial code sample1_go.cpp for details), libggo can instead of the traditional thread pool scheme. (read tutorial code sample10_co_pool.cpp and sample11_connection_pool.cpp for details)

  • ** tutorial directory contains many tutorial codes, including detailed instructions, so that develop can learn libgo library step by step. **

  • If you find any bugs, good suggestions, or use ambiguities, you can submit a issue or contact the author directly:
    Email: 289633152@qq.com

compile and use libgo :

  • Vcpkg:

If you have installed vcpkg, you can install it directly using vcpkg:
$ vcpkg install libgo

  • Linux:

    1.Use cmake to compile and install:

      $ mkdir build
      $ cd build
      $ cmake ..
    

    $ make debug #Skip it if you don`t want a debuggable versions.
    $ sudo make uninstall
    $ sudo make install

    2.Dynamic link to glibc: (put libgo at the front of link list)

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

    3.Full static link: (put libgo at the front of link list)

      g++ -std=c++11 test.cpp -llibgo -Wl,--whole-archive -lstatic_hook -lc -lpthread -Wl,--no-whole-archive [-lother_libs] -static
    
  • Windows: (3.0 is compatible with windows, just use master branch directly!)

    0.When using GitHub to download code on windows, we must pay attention to the problem of newline characters. Please install git correctly (using default options) and use git clone to download source code. (Do not download compressed packages)

    1.Use CMake to build project.

      #For example vs2015(x64):
      $ cmake .. -G"Visual Studio 14 2015 Win64"
    
      #For example vs2015(x86):
      $ cmake .. -G"Visual Studio 14 2015"
    

    2.If you want to execute the test code, please link the boost library. And set BOOST_ROOT in the cmake parameter:

      	For example:
      	$ cmake .. -G"Visual Studio 14 2015 Win64" -DBOOST_ROOT="e:\\boost_1_69_0"
    

performance

Like golang, libgo implements a complete scheduler (users only need to create a coroutine without concern for the execution, suspension and resource recovery of the coroutine). Therefore, libgo is qualified to compare the performance of single-threaded with golang (It is not qualified to do performance comparison in different ability).

Test environment:
2018 13-inch MAC notebook (CPU minimum)
Operating System: Mac OSX
CPU: 2.3 GHz Intel Core i5 (4 Core 8 Threads)
Test script: $test/golang/test.sh thread_number

Matters needing attention(WARNING):

TLS or non-reentrant library functions that depend on TLS implementation should be avoided as far as possible.
If it is unavoidable to use, we should pay attention to stop accessing the TLS data generated before handover after the process handover.

There are several kinds of behaviors that may cause the process switching:

  • The user calls co_yield to actively give up the cpu span.
  • Competitive Cooperative Lock, Channel Reading and Writing.
  • System Call of Sleep Series.
  • System calls waiting for events to trigger, such as poll, select, epoll_wait.
  • DNS-related system calls (gethostbyname series).
  • Connect, accept, data read-write operations on blocking sockets.
  • Data Read-Write Operation on Pipe.

System Call List of Hook on Linux System:

	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

The above system calls are all possible blocking system calls. The whole thread is no longer blocked in the process. During the blocking waiting period, the CPU can switch to other processes to execute.System calls executed in native threads by HOOK are 100% consistent with the behavior of the original system calls without any change.

	socket
	socketpair
	pipe
	pipe2
	close     
	__close
	fcntl     
	ioctl     
	getsockopt
	setsockopt
	dup       
	dup2      
	dup3      

The above system calls will not cause blocking, although they are also Hook, but will not completely change their behavior, only for tracking socket options and status.

System Call List of Hook on Windows System:

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