溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

網絡IO解決方案 — 協程框架的實現

發布時間:2020-07-01 00:18:49 來源:網絡 閱讀:15327 作者:南陽居士 欄目:建站服務器


網絡IO解決方案 — 協程框架的實現


協程這個概念很久了,好多程序員是實現過這個組件的,網上關于協程的文章,博客,論壇都是汗牛充棟,在知乎,github上面也有很多大牛寫了關于協程的心得體會。突發奇想,我也來實現一個這樣的組件,并測試了一下性能。借鑒了很多大牛的思想,閱讀了很多大牛的代碼。于是把整個思考過程寫下來。實現代碼?https://github.com/wangbojing/NtyCo

代碼簡單易讀,如果在你的項目中,NtyCo能夠為你解決些許工程問題,那就榮幸之至。


下面將部分的NtyCo的代碼貼出來。


NtyCo 支持多核多進程。

int?process_bind(void)?{

	int?num?=?sysconf(_SC_NPROCESSORS_CONF);

	pid_t?self_id?=?syscall(__NR_gettid);
	printf("selfid?-->?%d\n",?self_id);

	cpu_set_t?mask;

	CPU_ZERO(&mask);
	CPU_SET(self_id?%?num,?&mask);

	sched_setaffinity(0,?sizeof(mask),?&mask);

	mulcore_entry(9096?+?(self_id?%?num)?*?10);

}


NtyCo 上下文切換

首先來回顧一下x86_64寄存器的相關知識。x86_64 的寄存器有1664位寄存器,分別是:%rax, %rbx, %rcx, %esi, %edi, %rbp, %rsp, %r8, %r9, %r10, %r11, %r12,

%r13, %r14, %r15。

%rax 作為函數返回值使用的。

%rsp 棧指針寄存器,指向棧頂

%rdi, %rsi, %rdx, %rcx, %r8, %r9 用作函數參數,依次對應第1參數,第2參數。。。

%rbx, %rbp, %r12, %r13, %r14, %r15 用作數據存儲,遵循調用者使用規則,換句話說,就是隨便用。調用子函數之前要備份它,以防它被修改

%r10, %r11 用作數據存儲,就是使用前要先保存原值。

?

上下文切換,就是將CPU的寄存器暫時保存,再將即將運行的協程的上下文寄存器,分別mov到相對應的寄存器上。此時上下文完成切換。如下圖所示:


網絡IO解決方案 — 協程框架的實現



代碼如下

__asm__?(
"????.text??????????????????????????????????\n"
"???????.p2align?4,,15???????????????????????????????????\n"
".globl?_switch??????????????????????????????????????????\n"
".globl?__switch?????????????????????????????????????????\n"
"_switch:????????????????????????????????????????????????\n"
"__switch:???????????????????????????????????????????????\n"
"???????movq?%rsp,?0(%rsi)??????#?save?stack_pointer?????\n"
"???????movq?%rbp,?8(%rsi)??????#?save?frame_pointer?????\n"
"???????movq?(%rsp),?%rax???????#?save?insn_pointer??????\n"
"???????movq?%rax,?16(%rsi)??????????????????????????????\n"
"???????movq?%rbx,?24(%rsi)?????#?save?rbx,r12-r15???????\n"
"???????movq?%r12,?32(%rsi)??????????????????????????????\n"
"???????movq?%r13,?40(%rsi)??????????????????????????????\n"
"???????movq?%r14,?48(%rsi)??????????????????????????????\n"
"???????movq?%r15,?56(%rsi)??????????????????????????????\n"
"???????movq?56(%rdi),?%r15??????????????????????????????\n"
"???????movq?48(%rdi),?%r14??????????????????????????????\n"
"???????movq?40(%rdi),?%r13?????#?restore?rbx,r12-r15????\n"
"???????movq?32(%rdi),?%r12??????????????????????????????\n"
"???????movq?24(%rdi),?%rbx??????????????????????????????\n"
"???????movq?8(%rdi),?%rbp??????#?restore?frame_pointer??\n"
"???????movq?0(%rdi),?%rsp??????#?restore?stack_pointer??\n"
"???????movq?16(%rdi),?%rax?????#?restore?insn_pointer???\n"
"???????movq?%rax,?(%rsp)????????????????????????????????\n"
"???????ret??????????????????????????????????????????????\n"
);


協程的調度器

調度器的實現,有兩種方案,一種是生產者消費者模式,另一種多狀態運行。

網絡IO解決方案 — 協程框架的實現


邏輯代碼如下:

while?(1)?{
?
????????//遍歷睡眠集合,將滿足條件的加入到ready
????????nty_coroutine?*expired?=?NULL;
????????while?((expired?=?sleep_tree_expired(sched))?!=?)?{
????????????TAILQ_ADD(&sched->ready,?expired);
????????}
?
????????//遍歷等待集合,將滿足添加的加入到ready
????????nty_coroutine?*wait?=?NULL;
????????int?nready?=?epoll_wait(sched->epfd,?events,?EVENT_MAX,?1);
????????for?(i?=?0;i?<?nready;i?++)?{
????????????wait?=?wait_tree_search(events[i].data.fd);
????????????TAILQ_ADD(&sched->ready,?wait);
????????}
?
????????//?使用resume回復ready的協程運行權
????????while?(!TAILQ_EMPTY(&sched->ready))?{
????????????nty_coroutine?*ready?=?TAILQ_POP(sched->ready);
????????????resume(ready);
????????}
????}


多狀態運行

網絡IO解決方案 — 協程框架的實現

實現邏輯代碼如下:

while?(1)?{
?
????????//遍歷睡眠集合,使用resume恢復expired的協程運行權
????????nty_coroutine?*expired?=?NULL;
????????while?((expired?=?sleep_tree_expired(sched))?!=?)?{
????????????resume(expired);
????????}
?
????????//遍歷等待集合,使用resume恢復wait的協程運行權
????????nty_coroutine?*wait?=?NULL;
????????int?nready?=?epoll_wait(sched->epfd,?events,?EVENT_MAX,?1);
????????for?(i?=?0;i?<?nready;i?++)?{
????????????wait?=?wait_tree_search(events[i].data.fd);
????????????resume(wait);
????????}
?
????????//?使用resume恢復ready的協程運行權
????????while?(!TAILQ_EMPTY(sched->ready))?{
????????????nty_coroutine?*ready?=?TAILQ_POP(sched->ready);
????????????resume(ready);
????????}


性能測試

測試環境:4臺VMWare 虛擬機

1服務器 6G內存,4核CPU

3臺客戶端 2G內存,2核CPU

操作系統:ubuntu 14.04

服務器端測試代碼:https://github.com/wangbojing/NtyCo

客戶端測試代碼:https://github.com/wangbojing/c1000k_test/blob/master/client_mutlport_epoll.c

?

按照每一個連接啟動一個協程來測試。協程啟動數量能夠達70W無異常。



網絡IO解決方案 — 協程框架的實現


網絡IO解決方案 — 協程框架的實現



????BAT, 滴滴,今日頭條,美圖,美團等一線內推 技術崗位內推?

????QQ群935760465


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女