如何評價call_in_stack這個庫?

yuanzhubi/call_in_stack

yuanzhubi/call_in_stack

可以讓函數跳到一個新的棧上執行。還能安全的返回回來。

在協程之間無需棧拷貝實現了堆棧共享,雖然有些約束(在共享堆棧上執行的代碼不能發生堆棧切換。)

感覺對於stackful協程來說還是很重要的一個組件,為何過去好像無人實現類似的utility?也無人關注。。

這個作者的彙編和C++模版的混合使用也是有點驚艷。。。


我是作者(yuanzhubi) 我來簡單說幾句開發時的一些體驗。

0. call_in_stack就是讓一個函數用任何一塊內存作為棧來執行的庫,純頭文件的。可以讓協程創建的時候少分配些棧,執行函數的時候再按需使用。支持C++03(使用右值需要配置頭文件里或者編譯的時候定義一個紅。)。

1. 我工作的開發場景是C++ 03。所以右值的支持放到最近才支持,也沒有使用變長模版參數這樣的特性。

2. call_in_stack最早的名字是call_with_stack, 結果發現arm linux內核中有一個類似的同名函數(功能也類似,但是只固定支持一個void*參數,用起來頗似線程創建。。),所以把with換成了in。

3. X64和x86 gcc不支持naked屬性,我卻需要寫很多內嵌彙編,那麼編譯器進入一個函數到底會不會默認push ebp呢?解決這個問題我好費神,因為x64上不同優化等級這個問題答案也不同。

4. 多用編譯期常量比較操作,少用偏特化。實際要考慮的組合千變萬化,於是我盡量把ABI上的組合變化放在了內嵌彙編部分,這個部分已經沒有了類型信息,我就痛痛快快的做常量比較 if else了,O0優化也會幫你幹掉那些不需要的語句。

5. 蘋果MAC操作系統是21世紀才使用x86和x64的,x86的ABI和linux有點點輕微的差異,主要在long double和函數調用堆棧對齊上。

6. GCC內嵌彙編上的支持好勉強,我定義寄存器變數卻總是收到未初始化就使用的警告;我已經在內嵌彙編中ret了,卻總是警告我沒有給返回值。。吐槽點滿滿的,灑滿一身。為了避免給使用者在-Wall的時候產生很多警告,我也用了很多黑科技手段去避免警告還不讓性能有任何指令級的損失。

7.盡量避免C++模版編譯結果體積膨脹:類型聚合(type union)(自己的C++小工具系列5) - 知乎專欄 類型聚合是個好方法,讓我實現了用內嵌彙編去返回C++引用還不引起任何編譯器警告。有興趣的同學可以去瞅瞅源碼。

8. 接下來的計劃是支持lambda。因為好多人建議不僅僅是需要支持call_in_stack for function, 而是要讓一大塊代碼都能整體在一個新的stack執行。考慮到lambda的ABI是沒有公開的,打算做個wrapper去實現。


要知道在x64 glibc里,print或者cout一個long double浮點數會消耗超過6KB棧)。

???


call_in_stack現在支持C++成員函數和函數對象(含lambda了),支持一下

yuanzhubi/call_in_stack

看了下實現和介面依然很高效和簡介。


在golang成功的示範下,大家貌似又找到一條以前走不通現在又走得通的路了。在沒有編譯器輔助下的stackless協程,寫起來實在痛苦。而stackfull總是面臨棧大小的困擾:棧小了,稍微不小心就棧溢出;棧大了,內存地址空間頂不住。騰訊的libco為了解決這個問題,用了stackcopy方案,用時間換空間。在即想保留較小棧佔用,又偶爾需要較大棧空間的時候,call_in_stack就提供了一個嶄新的視角去解決這個矛盾。

希望有更多大牛來完善call_in_stack,使得支持x64 on Windows,以及c++函數。


剛看了這個庫,我覺得很酷,但在沒有協程的時候,我能想到的用途不多,也算一種酷酷的奇技淫巧吧,作者的確NB


推薦閱讀:

Unreal4有哪些令你印象深刻拍案叫絕的設計?
為什麼傳遞函數指針而不是函數本身?
剛開始做leetcode上的題,可以輸出正確結果,但總是超時,怎麼解決?

TAG:彙編語言 | C | 堆棧 | 協程 |