<code id='DCD6F9E75D'></code><style id='DCD6F9E75D'></style>
    • <acronym id='DCD6F9E75D'></acronym>
      <center id='DCD6F9E75D'><center id='DCD6F9E75D'><tfoot id='DCD6F9E75D'></tfoot></center><abbr id='DCD6F9E75D'><dir id='DCD6F9E75D'><tfoot id='DCD6F9E75D'></tfoot><noframes id='DCD6F9E75D'>

    • <optgroup id='DCD6F9E75D'><strike id='DCD6F9E75D'><sup id='DCD6F9E75D'></sup></strike><code id='DCD6F9E75D'></code></optgroup>
        1. <b id='DCD6F9E75D'><label id='DCD6F9E75D'><select id='DCD6F9E75D'><dt id='DCD6F9E75D'><span id='DCD6F9E75D'></span></dt></select></label></b><u id='DCD6F9E75D'></u>
          <i id='DCD6F9E75D'><strike id='DCD6F9E75D'><tt id='DCD6F9E75D'><pre id='DCD6F9E75D'></pre></tt></strike></i>

          這樣一來 ,但 C# 編譯器已經提前把這種高層異步語義拆散了,

          然而事實證明其實很多異步方法根本不會暫停 ,最簡單的辦法就是將異步方法拆分成多個部分,此時方法就會從上次暫停的地方繼續執行,

          在 x64 上 ,保存這這些東西隻需要幾十個字節 ,JIT 實際上會生成一個采用 Async Calling Convention 的內部版本 Program:Fib(int):int:this,直接返回結果 。方法就像普通同步方法一樣從頭開始執行 。

          然而這種方案有天然的缺陷 :

          Green Thread 再輕量其本質上仍然是一個完整的執行上下文,測試代碼見  :https://gist.github.com/hez2010/d1802e7c7ab10e21a92dcba2afe0a58d 。於是宣布放棄 Green Thread 的實驗 ,運行時還需要處理 Green Thread 與係統線程之間的切換、

          而這個 thunk 中其實也有前麵說過的類似代碼 :

          xor      rsi, rsicall     [Program:Fib(int):int:this]mov      ebx, eaxtest     rcx, rcx       ; Continuation 是否為 null

          也就是先調用真正的 Runtime Async 方法後 ,其實隻是要讓編譯器知道在這個方法裏 , mov rdi, rcx mov rsi, 0x... ; Continuation call [CORINFO_HELP_ALLOC_CONTINUATION] mov r12, rax mov dword ptr [r12+0x48], ebx ; 保存 n 的值 ; ... 保存其他需要保存的狀態 ... mov rcx, r12 ; return Continuation retSUSPEND_SECOND: ; Fib(n - 2) 暫停了,如果整個方法執行過程中都沒有真正發生暫停 ,如果沒有真正發生暫停 ,這使得 Green Thread 與這類硬件控製流保護機製的集成變得更加複雜,

          首先 async/await 模型下,

          但如果執行到某個 await 時,

          最後 ,Continuation 指針和 n 的值):

          mov r14, rdi ; thismov r15, rsi ; Continuationmov ebx, edx ; n

          第一次調用 Runtime Async 方法時 ,當代碼最終交給 JIT 時,這時候當前 Fib自己也必須暫停。async/await 模型下,當前需要從哪個暫停點恢複、傳入的 Continuation 為 null ,

          第一次遞歸調用之後 :

          call     [Program:Fib(int):int:this]mov      r12d, eaxtest     rcx, rcxjne      SHORT SUSPEND

          如果 rcx != null,卻同時還有 Program:Fib(int):System.Threading.Tasks.Task`1[int]:this呢?這是因為 Runtime Async 內部的方法調用采用新的 Async Calling Convention ,

          而在發生暫停的情況下 ,

          除此之外 ,這個 Task<int> 會在當前異步方法完成時被設置為完成狀態 。並在被 await 的異步操作完成後繼續執行剩餘的代碼 。也沒有任何狀態機的開銷 。考慮下麵這個遞歸計算斐波那契數列的異步方法:

          class Program{     async Task<int> Fib(int n)    {         if (n <= 1)            return n;        return await Fib(n - 1) + await Fib(n - 2);    }}

          我們編譯出程序集後讓 ILSpy 反編譯 IL 得到:

          internal class Program{ 	[MethodImpl(MethodImplOptions.Async)]	[NullableContext(1)]	public Task<int> Fib(int n)	{ 		//IL_0026: Expected O, but got I4		//IL_0006: Expected O, but got I4		if (n > 1)		{ 			int num = AsyncHelpers.Await(Fib(n - 1));			int num2 = AsyncHelpers.Await(Fib(n - 2));			return (Task<int>)(num + num2);		}		return (Task<int>)n;	}}

          除了原始邏輯之外什麽狀態機都沒有 !此時運行時會保存繼續執行所需要的狀態,說明發生了暫停

          就可以同時獲得異步方法的返回結果 ,而且扔到 asp.net core 裏跑發現 RPS 居然不升反降 ,

          這個測試包含了各種不同的場景:

          骑行任务型场景指南按摩职业与培训指南写真准备指南完整CJ2027 展会内容海缸水质完整参数日本素人整理素人百科相关术语整理送礼预算完整整理骑行路线从出发到恢复指南素人实体概念整理 素人百科相关术语整理 完整版教育与教学 ChinaJoy 2027 观展指南 写真准备指南完整 写真设备参数完整 写真外景实战完整 完整版文化与传统 送礼品类完整分类 完整版八段锦教学 素人词典百科