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)