jump label機(jī)制進(jìn)入Linux內(nèi)核已經(jīng)很多很多年了,它的目的是 消除分支。 為了達(dá)到這個(gè)目的,jump label的手段是 修改分支處的代碼。
~把代碼當(dāng)做數(shù)據(jù),代碼和數(shù)據(jù)在馮諾伊曼計(jì)算機(jī)中得到了統(tǒng)一~
本質(zhì)上,jump label作用于下面的邏輯:
靜態(tài)拆分成了下面的兩個(gè)邏輯,其一是:
或者,其二是:
但二者不能同時(shí)共存。顯然,這破壞了通用性和靈活性,帶來了高效!
這相當(dāng)于一個(gè)硬熔斷,具體詳情參見:
本文來一點(diǎn)可以看得見的東西,演示一下真實(shí)的jump label & static key。
先看下面的C代碼:
很簡單的代碼,也很正確。然而, 如果main函數(shù)是一個(gè)高頻調(diào)用的函數(shù),并且在E1,E2是不隨著代碼邏輯而發(fā)生變化,僅僅參數(shù)設(shè)定的情況下, 那么if語句盡量消除以消除不必要的分支預(yù)測(cè),而這正是jump label的用武之地!
我們下面用jump label機(jī)制來重寫上面的代碼,請(qǐng)看:
定義JUMP_LABEL宏編譯之,看看效果:
如何做到的呢?static_branch_true內(nèi)聯(lián)函數(shù)是如何判斷true or false的呢?
事實(shí)上,jump label邏輯修改了代碼段,取消了條件判斷!這一切都是在update_branch中發(fā)生的。我們看下update_branch調(diào)用之前,main函數(shù)的匯編碼:
在執(zhí)行了update_branch之后,main函數(shù)發(fā)生了變化:
看樣子就是這么回事!
之所以這件事可以發(fā)生得如此簡單,多虧了一個(gè)新的section,即__jump_table,我們通過objdump看看__jump_table的內(nèi)容:
通過jump_label_demo.c的struct entry結(jié)構(gòu)體,我們直到這個(gè)section中包含了多個(gè)3元組,包含3個(gè)字段:
需要修改的代碼地址。
需要jmp到的代碼地址。
匹配健。
我們看67064000 00000000按照小端就是0x400667,它就是需要修改的代碼地址,而6e064000 00000000按照小端則是0x40066e:
看來,這個(gè)__jump_table的item會(huì)將jmpq 40066c修改為jmpq 40066e,從而實(shí)現(xiàn)了 永久靜態(tài)分支。
最后,__jump_table的內(nèi)容就是在每一個(gè)內(nèi)聯(lián)的static_branch_true函數(shù)中被填充的,該參數(shù)的參數(shù)是一個(gè)key,它指示了branch entry三元組中的最后一個(gè)字段。
static_branch_true函數(shù)的內(nèi)聯(lián)非常重要,它實(shí)現(xiàn)了將branch entry三元組數(shù)據(jù)直接插入到__jump_table section,而不是共享同一個(gè)函數(shù)體。
總之,如果你看代碼還是覺得別扭,手敲一遍我上面的示例程序,就理解了,內(nèi)核里面的也就這么回事,總結(jié)一句話:
依靠運(yùn)行時(shí)修改代碼而不是依靠狀態(tài)數(shù)據(jù)來控制執(zhí)行流。
我不知道這對(duì)于所謂的 通用計(jì)算機(jī)程序設(shè)計(jì) 是不是反其道而行之,但在效果上,它確實(shí)是一匹好馬。不禁感嘆, 硬編碼讀起來是丑陋的,但執(zhí)行起來卻是高效的!
靈活性換高效率,得不償失,我是這樣以為。jump label的本質(zhì)在于, 將同時(shí)刻存在的一套代碼沿著時(shí)間線在可預(yù)期的固定時(shí)間點(diǎn)上分割成邏輯相反的兩套代碼。
硬件性能的提升將會(huì)證明jump label就是個(gè)笑話。
說兩句好話,Linux內(nèi)核參數(shù),sysctl變量基本上就可以通過jump label來運(yùn)作,從而替代if判斷。
原文鏈接:https://blog.csdn.net/dog250/article/details/106715700
編輯:lyn
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7139瀏覽量
89568 -
邏輯
+關(guān)注
關(guān)注
2文章
833瀏覽量
29515 -
代碼
+關(guān)注
關(guān)注
30文章
4825瀏覽量
69038 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
316瀏覽量
21741
原文標(biāo)題:Linux內(nèi)核jump label與static key的原理與示例
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論