.NET 8 的 green thread 非同步模型被擱置了

張善友發表於2023-09-19

.NET 平臺上的green thread 非同步模型實驗結果最近出來了,具體參見:https://github.com/dotnet/runtimelab/issues/2398 ,實驗結果總結一下就是在.NET和 ASP.NET Core中實現Green Thread是可行的。Green Thread 在.NET執行時環境中的基本成本和好處,以及與非同步程式設計模型的互動和挑戰。如果引入了全新的非同步程式設計模型,對於.NET開發人員來說,Green Thread 和現有非同步模型async/await 之間的互動非常複雜。因此,決定暫停綠色執行緒試驗,繼續改進現有的async/await模型,以便在.NET中開發非同步程式碼。

文章對為什麼要進行Green thread的實驗的總結一下就這麼幾點:

  1. .NET的非同步程式設計模型簡化了應用程式的非同步程式碼編寫,對於增強I/O繫結方案的可伸縮性非常關鍵。
  2. I/O繫結程式碼經常處於等待狀態,如等待網路返回資料。非同步程式碼提高了可伸縮性,顯著降低了等待I/O的請求成本。
  3. 非同步C#程式碼的優勢是在等待I/O操作時的低成本,並且允許伺服器並行處理大量請求。
  4. 但非同步編碼也有挑戰,因為開發者需要確定哪些方法應該非同步化。全面非同步化不現實,因為非同步方法有效能、型別限制,並且程式設計模型複雜。
  5. Green thread的目的是簡化程式設計模型,使得所有程式碼可以以同步方式編寫,但仍保持可伸縮性和效能。
  6. Green thread在其他程式設計環境中已經被驗證為有效,現在的考慮是它是否適用於C#,特別是考慮到存在的async/await模型。

文章裡也對擱置Green thread的結論總結幾點:

  1. Green thread為.NET開發人員提供了一個全新的非同步程式設計模型。 asp. net core benchmark 顯示 green thread 效能不如現有的 async/await,async/await 達到 178,620 rps 的同時 green thread 只達到了 162,019 rps, .NET 平臺是目前為止唯一一個同時實現了Green Thread 和async/await 非同步模型的平臺,這就讓我們有了一個橫向比較兩種程式設計模型的平臺,這也就破案了在社群中 非同步程式設計模型哪個更快的爭論,這裡有個非常好的面試題就說 golang,nodejs,java等等他們實現的非同步程式設計模型分別是哪一種,他們有什麼優缺點等。
  2. Green thread與現有的非同步模型之間的互動是複雜的。特別是從Green thread程式碼呼叫非同步方法需要轉換到非同步程式碼的同步模式,這在常規執行緒上不是一個好的選擇。 micro benchmark 顯示深 green thread 呼叫棧的效能遠不如深 async/await 呼叫鏈。
  3. 在Green thread模型中,與本機程式碼的互操作性是複雜和相對較慢的。基於P/Invoke的基準測試顯示,Green thread上的操作成本明顯增加。 100,000,000 次 P/Invoke 從原來的 300ms 變成需要 1800ms。
  4. Green thread在與某些特定特性如執行緒區域性靜態變數和本機執行緒狀態互動時存在功能上的問題。 thread local 變數的支援以及暴露 native thread 狀態變得非常難以實現。
  5. Green thread與某些安全緩解措施,如防止面向返回的程式設計的影子堆疊( shadow stacks),的互動是具有挑戰性的。
  6. 在某些關鍵場景中,Green thread模型的速度有可能超過非同步,但這種效能提升的代價是其他場景下的效能下降,以及需要放棄一些相容性和特性。
  7. 一個未解之謎是,透過最佳化非同步,是否可以讓Green thread在效能上超過非同步。
  8. 開發團隊發現以上問題在其它使用 green thread 的語言中同樣存在。

文章後面的討論值得看一看,其中rcollette 的觀點特別有意思:https://github.com/dotnet/runtimelab/issues/2398#issuecomment-1713003525 

這篇關於loom/Java 21的演講對於那些希望深入瞭解綠色執行緒的人來說非常不錯。 https://blog.jetbrains.com/idea/2023/05/new-livestream-virtual-threads-and-structured-concurrency-in-java-2021-with-loom/

我預計在現實世界中,它們(對現有程式碼)有益的情境會非常有限。你需要大量的阻塞IO,對嗎?到執行緒池飢餓成為一個問題的程度。

在Java世界中,這很快就會發生,原因有以下幾點:

  1. Java沒有標準的非阻塞資料庫驅動規範。Java在開始研究綠色執行緒之前應該先解決這個問題。容易說“你的操作持續時間太長”,但有些事務本質上執行時間很長,並且有時候你無法控制。這是主要的問題。
  2. 對於一些開發人員來說,反應式非同步模式/API是一個心智跳躍,他們只是試圖避免它(並不是說這是對的,但這種情況經常發生)。這比JS中的Promise巢狀還要糟糕。對於你使用的每一個方法,你都必須考慮我是否返回相同的型別,我是否返回另一個promise(Future),我是處理一個集合還是單個值,都需要不同的方法呼叫,等等。你還會遇到執行緒上下文的情況,比如事務,日誌MDC等,在反應式模型中似乎毫無理由地失敗,這再次讓開發人員失去信心。說“他們是開發人員,他們應該做得對或離開這個行業”都把責任推到了平臺開發者身上來提供優雅的解決方案。這是Java存在的一個問題,並且坦白說,我不希望這種情況在.NET中發生,因為Java中這種不夠優雅的原因正是我更喜歡.NET的原因。

相關文章