You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- 多核环境下 CPU 缓存亲和性:因为 CPU 本身有高效的多级缓存,虽然 CPU 多级缓存容量较内存小的多,但访问效率却远高于内存,单线程调度方式下,可以方便编译器有效地进行 CPU 缓存使用优化,使运行指令和共享数据尽可能放置在 CPU 缓存中,而如果采用多线程调度方式,多个线程间共享的数据就可能使 CPU 缓存失效,会造成调度线程越多,协程的运行效率越低的问题;
- **Windows:** select/poll/iocp/Windows 窗口消息,其中 iocp 为 Windows 平台下的内核级高效事件引擎;libfiber 支持采用界面消息引擎做为底层的事件引擎,这样在编写 Windows 界面程序的网络模块时便可以使用协程方式了,之前人们在 Windows 平台编写界面程序的网络模块时,一般采用以下两种方式:
网络协程库既然面向网络,自然离不开域名的协程化支持,现在很多网络协程库的设计者往往忽视了这一点,有些网络协程库在使用系统 API 进行域名解析时为了防止阻塞协程调度器,将域名解析过程(即调用 gethostbyname/getaddrinfo)扔给独立的线程去执行,当调用系统 API 进行域名解析并发量较大时必然会造成很多线程资源被占用。在 libfiber 中集成了第三方 dns 源码,实现了域名解析过程的协程化,占用更低的系统资源,基本满足了大部分服务端应用系统对于域名解析的需求。
相对于栈拷贝时的时间损耗,在使用共享栈方式编程时有一点需要特别注意:创建在栈上的变量不能在协程之间或协程与线程之间共享,即是说,一个协程 F1 中的变量 A 传递给另一个协程 F2,并等待 F2 处理后返回,此时的 A 变量不能被创建在 F1 的栈上,因为运行栈在由 F1 切换到 F2 时,变量 A 的地址空间“暂时消失了”,此时变成了 F2 的栈空间,如果该变量在 F2 中继续被使用的话,就会存在地址非法使用的问题;解决变量在协程间共享的方法是将变量创建在堆上(即用 malloc 或 new 创建)。
234
+
235
+
注:共享栈的想法最初应该是在腾讯的 libco 中提出的,应该也是为了解决大并发时的内存占用问题。
236
+
237
+
### 3.5、域名解析
238
+
网络协程库既然面向网络,自然离不开域名的协程化支持,现在很多网络协程库的设计者往往忽视了这一点,有些网络协程库在使用系统 API 进行域名解析时为了防止阻塞协程调度器,将域名解析过程(即调用 gethostbyname/getaddrinfo)扔给独立的线程去执行,当调用系统 API 进行域名解析并发量较大时必然会造成很多线程资源被占用。在 libfiber 早期通过集成第三方 dns 源码,实现了域名解析过程的协程化,基本满足了大部分服务端应用系统对于域名解析的需求;后来因为跨平台性及代码安全性的需要,在 libfiber 中实现了与域名解析相关的 DNS 协议,替换了第三方 DNS 库。
239
+
240
+
### 3.6、Hook 系统 API
234
241
相对于网络协程的出现时间,很多网络库很早就存在了,并且大部分已有的网络库都是阻塞式的,要改造这些网络库使之协程化的成本是非常巨大的,我们不可能采用协程方式将这些网络库重新实现一遍,目前一个广泛采用的方案是 Hook 与 IO 相关的系统中 API,在 Unix 平台上 Hook 系统 API 相对简单,在初始化时,先加载并保留系统 API 的原始地址,然后编写一个与系统 API 函数名相同且参数也相同的函数,将这段代码与应用代码一起编译,则编译器会优先使用这些 Hook API,下面的代码给出了在 Unix 平台上 Hook 系统 API 的简单示例:
0 commit comments