.NET 8 是一個長期支援(LTS) 版本。這篇文章涵蓋了推動增強功能優先順序排序和選擇開發的主要主題和目標。.NET 8 預覽版和釋出候選版本將每月交付一次。像往常一樣,最終版本將在 11 月的某個時候在 .NET Conf 上釋出。
.NET 版本包括產品、庫、執行時和工具,代表 Microsoft 內外多個團隊之間的協作。這篇博文中涵蓋的更廣泛的主題並不包含 .NET 8 的所有關鍵場景和投資。它們代表了很大的領域,但只是進入 .NET 8 的所有重要工作的一部分。我們計劃對 ASP.NET Core, Blazor, EF Core, WinForms, WPF 和其他平臺進行廣泛的投資。
歡迎使用 .NET 8
去年年底,我們釋出了 .NET 7,這是 .NET 團隊與支援該版本的令人驚歎的社群合作的結果,該版本有10,000多名社群成員提供了超過28,000個社群貢獻。.NET 7 是當今構建應用程式的首選框架。該版本將平臺與對 ARM64 的原生支援和對 Linux 的增強支援統一起來。它有助於透過 .NET MAUI 等工具使您的應用程式現代化,這些工具可以從同一程式碼庫構建跨平臺的移動和桌面應用程式。它包括對 API 效能的改進,並使構建和部署分散式雲原生應用程式變得更加容易。. NET 7 透過改進 C# 11 減少了必要的程式碼量,簡化了構建應用程式的體驗,並使得僅用幾行程式碼就可以建立和配置 API。從幫助除錯雲 API 整合到直接從 .NET SDK 構建容器的開發隧道,對工具進行了大量改進,幫助開發人員提高工作效率。
我們將在整個版本中更新 .NET 8 中的新增功能。
您可以透過向下滾動閱讀我們在預覽1中釋出的內容。首先,讓我們展望一下 .NET 8 的願景。
雲原生開發者的最佳平臺和工具
我們相信 .NET 開發人員應該能夠將他們的應用程式快速遷移到雲中,在不影響效能的情況下擴充套件他們的應用程式,並根據可操作的資料和關於您的應用程式在生產中的反饋來改進他們的應用程式。我們將投資於透過持續整合和部署更輕鬆地管理本地開發和測試的完整端到端體驗。我們的目標是讓微服務架構的實施以及容器的構建和部署變得更加容易。
雲原生是一個術語,用於描述專門為在雲端計算環境中部署而構建的應用程式的架構和設計。雲原生背後的主要思想是利用雲端計算平臺提供的優勢,例如可擴充套件性、彈性和自我修復,來建立高度可擴充套件和有彈性的應用程式。這提供了靈活性,並避免了為支援增長而對硬體和軟體進行潛在的過度投資。許多開發人員將雲原生與微服務、容器編排 (Kubernetes) 和“即服務”產品等概念聯絡在一起。
使用 MAUI 和 Blazor 混合進行跨平臺移動和桌面開發的絕佳體驗
在 .NET 7 期間,我們釋出了 .NET 多平臺應用程式使用者介面 (MAUI) SDK 和 Visual Studio 工具支援。.NET MAUI 提供了一個框架,用於使用單個 C# 程式碼庫為執行 Android、iOS、macOS 和 Windows 的移動和桌面裝置建立本機應用程式。除了支援 XAML UI 之外,您還可以使用 Blazor 構建具有 Razor UI 元件的混合應用程式,這些應用程式可以訪問本機裝置平臺並在移動、桌面和 Web 之間共享。.NET 團隊計劃以這些經驗為基礎,專注於提高 SDK 和工具的質量、穩定性、效能和整合度。
勢頭:根據您的意見繼續關注質量和效能
.NET 的每個版本都包括對 API、庫和框架的效能、質量、穩定性和易用性的改進,它們構成了活躍且不斷髮展的 .NET 生態系統。其中許多改進是由客戶和社群成員確定並優先考慮的。.NET 8 將遵循相同的趨勢,依靠您高度重視的反饋來幫助指導我們的願景並推動我們的重點。
瞭解最新情況並保持最新狀態
.NET 升級幫助是一個有價值的工具,可以幫助開發人員將他們的應用程式從舊版本的 .NET Framework 遷移到新版本。該工具的最新版本具有改進的功能,可以支援新場景並處理更多案例。有了這個工具,開發人員現在可以輕鬆地將他們的應用程式升級到 .NET 6或 .NET 7。
該工具可以自動檢測並建議需要對程式碼進行的更改,以確保與較新版本的框架相容。此外,它還可以處理更復雜的場景,例如升級使用第三方庫的應用程式以及與更新的平臺功能整合。這些改進使 .NET 升級輔助成為那些希望保持其應用程式最新並利用最新的 .NET 功能的開發人員的不可或缺的工具。該工具最近作為 Visual Studio 擴充套件引入。可幫助您從舒適的 Visual Studio 升級。
以 .NET 8 為目標
要以 .NET 8 為目標,您首先需要確保從 Microsoft 官方網站安裝了 .NET 8 SDK。接下來,您可以建立一個新專案,並透過在專案設定中設定適當的目標框架來指定您希望以 .NET 8 為目標。
您還可以透過更改專案屬性中的目標框架,將現有專案更新為面向 .NET 8。為此,請在 Visual Studio 或您喜歡的 IDE 中右鍵單擊專案,選擇“屬性”,然後選擇“應用程式”選項卡。從那裡,您可以選擇要使用的目標框架版本。這將設定適當的目標框架:
<TargetFramework>net8.0</TargetFramework>
請記住,以 .NET 8 為目標可能需要更改您的程式碼或依賴項,因為 API 或其他功能可能與以前版本的 .NET 有所不同。最好檢視 .NET 8 的文件和發行說明,以確保您的程式碼和依賴項與新版本相容。
.NET 8 預覽版 1 中的新增功能
我們的第一個預覽版包含您今天就可以試用的新功能。以下是預期結果的摘要。有關詳細的發行說明和重大更改,請閱讀 .NET 8 中的新增功能。
Native AOT
第一個 NativeAOT 功能在 .NET 7 和目標控制檯應用程式中釋出。Ahead-of-Time (AOT)編譯是 .NET 中的一項重要功能,可以對 .NET 應用程式的效能產生重大影響。感謝 Adeel 和 Filip 將 NativeAOT 功能引入 macOS 進行預覽 1。.NET 團隊將專注於完善 .NET 8 的一些基礎知識,例如大小(請參閱dotnet/runtime#79003)。使用 NativeAOT 釋出應用程式會建立一個完全獨立的應用程式版本,不需要單獨的執行時,因為所有內容都包含在單個檔案中。從預覽版1開始,這個檔案變小了。事實上,Linux 版本現在最多縮小了 50%。
以下是包含整個 .NET 執行時的 Native AOT 的“Hello, World”應用程式的大小:
NativeAOT 將繼續擴充套件並瞄準 .NET 8 中的其他應用場景,因此請繼續關注此部落格以獲取未來更新!
如果您不熟悉 AOT,這裡有一些 AOT 提供的好處:
- 減少記憶體佔用:與 JIT 編譯程式碼相比,AOT 編譯程式碼需要更少的記憶體,因為 JIT 編譯器生成 AOT 編譯應用程式不需要的中間程式碼。這對於記憶體有限的裝置尤其有益,例如嵌入式系統和移動裝置。
- 改進的啟動時間:與 JIT 編譯程式碼相比,AOT 編譯程式碼啟動速度更快,因為它消除了 JIT 編譯器生成中間程式碼並針對特定硬體和軟體環境最佳化程式碼的需要。這對於必須快速啟動的應用程式尤其有利,例如系統服務、無伺服器“功能”和後臺任務。
- 延長電池壽命:與 JIT 編譯程式碼相比,AOT 編譯程式碼消耗的電量更少,因為它消除了 JIT 編譯器生成中間程式碼並針對特定硬體和軟體環境最佳化程式碼的需要。這對於依賴電池的裝置(例如移動裝置)尤其有益。
.NET 容器映象
.NET 開發人員可以使用容器映象以輕量級、可移植的格式打包和部署他們的應用程式,這種格式可以在不同環境中執行並且可以輕鬆部署到雲端中。關於如何將容器映象用於 .NET 應用程式,預覽版 1 做出了以下改進:
- 將預設 Linux 發行版更新為 Debian 12:.NET 容器映象現在使用 Debian 12 (Bookworm),我們預計將在 2023 年年中釋出。Debian 用於方便的標籤,8.0如8.0-bookworm-slim。
- 標籤更改:.NET 8 預覽容器映象將使用8.0-preview 作為標籤(不是8.0)並在 Release Candidate 版本過渡到8.0。這種方法的目標是更清楚地描述預覽版。這是根據社群請求進行的更改。
- 與非根(non-root)使用者一起執行容器映象:儘管容器基礎映象幾乎總是配置為與根使用者一起執行——這種設定往往會保留在生產環境中——但它並不總是最好的方法。然而,將每個應用程式配置為擁有不同的使用者是一件很痛苦的事情,而且容器映象不會附帶適合容器工作負載的非根使用者。
.NET 8 提供了一種更好的方法。從預覽版 1 開始,我們釋出的所有容器映象都將支援非根配置。以下是用於以非根身份為 Dockerfiles 執行容器的單行示例:
USER app
此外,您現在可以使用 -u app。預設埠已從埠80更改為8080。這是啟用非根方案所必需的重大更改,因為埠80是特權埠。
執行時和庫
處理隨機性的實用方法
System.Random 和 System.Security.Cryptography.RandomNumberGenerator 都有實用方法 GetItems 以用於從輸入集中隨機選擇專案(“用替換”),以及用於隨機化跨度順序的實用方法 Shuffle。
Shuffle 有助於減少機器學習中的訓練偏差(因此第一件事並不總是訓練,最後一件事總是測試):
YourType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);
IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);
DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);
IDataView predictions = model.Transform(split.TestSet);
...
我們玩個遊戲好嗎?玩西蒙遊戲怎麼樣?
private static ReadOnlySpan<Button> s_allButtons = new[]
{
Button.Red,
Button.Green,
Button.Blue,
Button.Yellow,
};
...
Button[] thisRound = Random.Shared.GetItems(s_allButtons, 31);
// rest of game goes here ...
System.Numerics 和 System.Runtime.Intrinsics
在可能的情況下,我們將 Vector256<T> 重新實現為內部 2x Vector128<T> ops:dotnet/runtime#76221。這能使一些函式部分加速,例如在 Arm64 上 Vector128.IsHardwareAccelerated == true 但 Vector256.IsHardwareAccelerated == false。
我們新增了 Vector512<T> 初始託管實現:dotnet/runtime#76642。與之前的工作項非常相似,這在內部實現為 2x Vector256<T> ops(因此間接實現為 4x Vector128 ops)。這能使一些函式部分加速,即使 Vector512.IsHardwareAccelerated == false 注意:Vector512 還沒有直接加速,即使底層硬體支援它也是如此。此類功能應在未來的預覽版中啟用。
重寫 Matrix3x2 和 Matrix4x4 以更好地利用硬體加速:dotnet/runtime#80091。這能使某些基準測試的效能提升高達 48 倍。6-10倍的改進更為常見。
注意:預覽版2會對 Quaternion 和 Plane 進行改進。
Hardware Intrinsics 現在用 ConstExpected 屬性進行註釋:dotnet/runtime#80192。這能確保使用者知道底層硬體何時需要常量,因此非常量值何時可能會意外損害效能。
將 Lerp API 新增到 IFloatingPointIeee754<TSelf> 從而新增到 float (System.Single), double (System.Double)和 System.Half和: dotnet/runtime#81186。這能有效且正確地執行兩個值之間的線性插值。
JSON 改進
我們不斷改進 System.Text.Json,專注於增強原始碼生成器在 NativeAOT 應用程式中與 ASP.NET Core 一起使用時的效能和可靠性。下表顯示了預覽版 1 附帶的新功能:
- 缺少成員處理 dotnet/runtime#79945
現在可以配置物件反序列化行為,底層 JSON 負載包含無法對映到反序列化 POCO 型別成員的屬性時都可以適用。這可以透過設定一個 JsonUnmappedMemberHandling 值來控制,也可以作為 POCO 型別本身的註釋,全域性上 JsonSerializerOptions 或透過自定義 JsonTypeInfo 相關型別的合同以程式設計方式進行控制:
JsonSerializer.Deserialize<MyPoco>("""{"Id" : 42, "AnotherId" : -1 }""");
// JsonException : The JSON property 'AnotherId' could not be mapped to any .NET member contained in type 'MyPoco'.
[JsonUnmappedMemberHandling(JsonUnmappedMemberHandling.Disallow)]
public class MyPoco
{
public int Id { get; set; }
}
- 源生成器支援 required 和 init 屬性 dotnet/runtime#79828
源生成器現在支援序列化具有 required 和 init 屬性的型別,正如當前在基於反射的序列化中所支援的那樣。 - 介面層次結構支援 dotnet/runtime#78788
System.Text.Json 現在支援從介面層次結構序列化屬性:
IDerived value = new Derived { Base = 0, Derived =1 };
JsonSerializer.Serialize(value); // {"Base":0,"Derived":1}
public interface IBase
{
public int Base { get; set; }
}
public interface IDerived : IBase
{
public int Derived { get; set; }
}
public class Derived : IDerived
{
public int Base { get; set; }
public int Derived { get; set; }
}
- Snake Case 和 Kebab Case dotnet/runtime#69613
該庫現在附帶了 snake_case 的命名策略和 kebab-case 屬性名稱轉換。它們的用法與現有的 camelCase 命名策略類似:
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
JsonSerializer.Serialize(new { PropertyName = "value" }, options); // { "property_name" : "value" }
現在可以使用以下命名策略:
namespace System.Text.Json;
public class JsonNamingPolicy
{
public static JsonNamingPolicy CamelCase { get; }
public static JsonNamingPolicy KebabCaseLower { get; }
public static JsonNamingPolicy KebabCaseUpper { get; }
public static JsonNamingPolicy SnakeCaseLower { get; }
public static JsonNamingPolicy SnakeCaseUpper { get; }
}
感謝 @YohDeadfall 貢獻了實施。
- 新增 JsonSerializer.MakeReadOnly() 和 IsReadOnly API dotnet/runtime#74431JsonSerializerOptions 類一直使用可凍結語義,但直到現在凍結只能透過將例項傳遞給其中一種 JsonSerializer 方法來隱式完成。新增新 API 後,使用者可以明確控制何時 JsonSerializerOptions 應凍結其例項:
public class MySerializer
{
private JsonSerializerOptions Options { get; }
public MySerializer()
{
Options = new JsonSerializerOptions(JsonSerializerDefaults.Web) { Converters = { new MyCustomConverter() } };
Options.MakeReadOnly(); // Make read-only before exposing the property.
}
}
核心庫中以效能為中心的全新型別
多個新型別已新增到核心庫中,開發人員能夠利用新型別在常見場景中提高程式碼的效能。
新的名稱空間 System.Collections.Frozen 提供 FrozenDictionary<TKey, TValue> 和FrozenSet<T> 集合。這些型別提供了一個不可變的表面區域,一旦建立,鍵或值就不可以進行任何更改。這反過來又使集合能夠根據提供的資料更好地最佳化後續讀取操作(例如 TryGetValue),從而使其能夠在構造期有更多時間來最佳化所有未來的訪問。這對於第一次使用時填充、且需在長期服務期間持續存在的集合特別有用,例如:
private static readonly FrozenDictionary<string, bool> s_configurationData =
LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);
...
if (s_configurationData.TryGetValue(key, out bool setting) && setting)
{
Process();
}
現有型別 ImmutableArray<T>.Builder 還獲得了一種將其內容高效轉換為 ImmutableArray<T> 的新方法。.NET 8 引入了DrainToImmutable(),它將當前內容作為不可變陣列返回,並將構建器的集合重置為零長度陣列,它會選擇最有效的方法來執行此操作。基於元素的計數,我們可以使用此方法代替有條件地呼叫 ToImmutable()或 MoveToImmutable()。
新型別的另一個例子是 IndexOfAnyValues<T>,它能幫助開發人員預先投入一些時間以換取以後更快的執行速度。除了像 IndexOfAnyInRange 之類的新方法之外,還新增了接受 IndexOfAnyValues<T> 例項的新過載 IndexOfAny ,可以建立例項來表示要搜尋的一組 T 值。此例項的建立處理派生任何必要的資料以最佳化後續搜尋。例如,如果您經常搜尋所有 ASCII 字母和數字以及一些標點符號字元,您之前可能會這樣寫:
private static readonly char[] s_chars = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray();
...
int i = str.IndexOfAny(s_chars);
然而,這要求沒有任何型別的向量化能夠提高搜尋效率,要麼需要在每次呼叫 IndexOfAny 時花時間計算必要的狀態以加速操作。現在,您可以這樣寫:
private static readonly IndexOfAnyValues<char> s_chars = IndexOfAnyValues.Create("-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
...
int i = str.AsSpan().IndexOfAny(s_chars);
預先計算所有該狀態一次,以便在每次後續呼叫時都可以重用 IndexOfAny。
新型別 CompositeFormat 會自己反覆這種模式。.NET 長期以來一直支援透過 API 進行字串格式化,例如 string.Format 和 StringBuilder.AppendFormat,例如:
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, "Range from {0} to {1}", min, max);
C# 6 新增了對字串插值的支援,然後 C# 10 結合 .NET 6 顯著提高了這些操作的效率,使得相同的操作可以寫成:
static string GetMessage(int min, int max) =>
string.Create(CultureInfo.InvariantCulture, $"Range from {min} to {max}");
但是它是在編譯時而不是在每次呼叫 string.Format 時執行可以預先計算的工作。 而這需要在編譯時就能獲取到格式字串,以便可以在編譯時對其進行解析……如果它直到執行時才獲取到怎麼辦,例如,如果它是從資原始檔或其他動態方式載入的?為此,.NET 8 新增了 CompositeFormat 型別。與 IndexOfAnyValues<T> 一樣,它可以執行每次使用時需要執行的操作,然後將其取出執行一次。
private static readonly CompositeFormat s_rangeMessage = CompositeFormat.Parse(LoadRangeMessageResource());
...
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, s_rangeMessage, min, max);
這些新的過載還支援泛型引數,以避免裝箱開銷(boxing overheads)將所有內容都識別為 object。
.NET 8 預覽版 1 還增加了對新的以效能為中心的雜湊演算法的支援,包括新的 XxHash3 和 XxHash128 型別,它們提供了快速 XXH3 和 XXH128 雜湊演算法的實現。
.NET SDK
dotnet publish 與 dotnet pack 預設生產 Release 資產
Publish(釋出)和 Pack(打包)動詞的目的是產生生產資產,這意味著它們應該生產Release 資產。在 .NET 8 中,他們將預設執行此操作。
此功能由 PublishRelease 和 PackRelease 布林屬性控制。預設為 true。
用 dotnet publish 演示該功能最簡單:
/app# dotnet new console
/app# dotnet build
app -> /app/bin/Debug/net8.0/app.dll
/app# dotnet publish
app -> /app/bin/Release/net8.0/app.dll
app -> /app/bin/Release/net8.0/publish/
/app# dotnet publish -p:PublishRelease=false
app -> /app/bin/Debug/net8.0/app.dll
app -> /app/bin/Debug/net8.0/publish/
請注意,PublishRelease 並且 PackRelease 也存在於從 7.0.200 SDK 開始的 .NET 7 中。它們在 .NET 7 中是可選的,並且必須設定 true 才能執行相同的行為。
請參閱重大更改相關文件:
Linux 支援
從 dotnet/dotnet 構建您自己的 .NET
.NET 現在可以直接從 dotnet/dotnet 儲存庫在 Linux 上構建。它使用 dotnet/source-build 構建 .NET 執行時、工具和 SDK。例如,這與 Red Hat 和 Canonical 用於構建 .NET 的構建相同。隨著時間的推移,我們將擴充套件其功能以支援 macOS 和 Windows。
請參閱構建說明以在您自己的計算機上構建 VMR。對於許多人來說,在容器中構建是最簡單的方法,因為我們的 dotnet-buildtools/prereqs 容器映象包含所有必需的依賴項。
我們稱這個新儲存庫為 Virtual Mono Repository (VMR)。它具有真正的 monorepo 的優勢,這多虧了開發者們每天在眾多現有儲存庫中(更有效地)所做的定期更新。我們相信,VMR 和更小的“工作儲存庫”之間的分離是 .NET 專案的未來。我們希望在 VMR 中更容易構建橫切功能,但是,我們目前還沒有實現。
從原始碼構建 .NET 並將其構建成一個完整產品是可行的,我們認為這個新方法就是我們向其邁出的重要一步。
在 .NET 8 之前,從源構建是可行的,但需要從與釋出版本相對應的 dotnet/installer commit 提交建立 “source tarball” 。您不再需要進行這一操作。儲存庫將有與每個釋出版本對應的標籤,以及持續跟蹤產品狀態的 main 和 release/8.0-previewN 分支。
.NET 8 + Ubuntu Chiseled容器映象
我們正在釋出安裝了 .NET 8 的 Ubuntu Chiseled 映象. 相比常規容器,這種型別的映象適用於希望使用有裝置式計算優勢的開發人員。我們預計,當 .NET 8上線時,Canonical 和 Microsoft 都將支援 Ubuntu chiseled 映象。
我們計劃從 .NET 8 開始,釋出以 Ubuntu Chiseled 形式的 dotnet/monitor 映象。值得一提的是,monitor 映象是我們釋出的生產應用映象。
Chiseled images 有多種優勢:
- 超小影像(減小尺寸和攻擊面)
- 沒有包管理器(避免整類攻擊)
- 沒有shell外殼(避免整類攻擊)
- 沒有 root(避免整類攻擊)
您可以由此 aspnetapp sample 檢視生產中的的 Chiseled 容器映象。使用時,您只需要更改一行程式碼。
.NET 6 和 .NET 7 版本的 Chiseled 映象現在已被髮布到 nightly 儲存庫中。
Linux 支援和基線目標
我們正在更新支援 .NET 8 的 Linux 系統的最低基線。有三個變化需要注意。
- .NET 產品將針對 Ubuntu 16.04 版本進行構建,適用於所有體系結構。這對於定義 .NET 8 所需最低的 glibc 版本非常重要。例如,由於此項更改,.NET 8 將甚至無法在 Ubuntu 14.04 上啟動。
- 對於 Red Hat Enterprise Linux(RHEL),我們將支援 RHEL 8+,啟用 RHEL 7。
- 我們只會釋出 RHEL 的支援宣告,但是,我們希望也能支援其他 RHEL ecosystem distros 生態系統發行版。
重大變化主要就這些。我們仍將支援在 Arm32、Arm64 和 x64 架構上基礎上使用 Linux。
請注意,這些更改僅適用於 Microsoft 內部版本。使用 source-build 構建的不同組織可能情況不同,通常為了一個構建生成構建版本僅適用於一個發行版版本,例如 Ubuntu 24.04。
下面演示了 Ubuntu 16.04 glibc 版本以及其用於其他發行版的模式。
$ docker run --rm ubuntu:16.04 ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu11.3) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
程式碼的生成
社群 PRs (非常感謝 JIT 論壇的 contributors!)
- @am11 更新了 CLRConfiguration 和 jithost 中的 env 變數 PR#77025。
- @En3Tho 將 (X & 1) != 0 最佳化為 (X & 1) 和 (X & 1) == 0 以及 ((NOT X) & 1) in PR#74806, 並修復了與 faulty LIR range 相關的漏 PR#77166。
- @MichalPetryka 實現了Type.IsEnum 和 Type.GetEnumUnderlyingType 在 PR#71685的內部函式, 並將MemoryMarshal.GetArrayDataReference 轉換為 JIT 內部函式 PR#79760。
- @pedrobsaila 在 PR#62689 中做出了第一個 PR 貢獻,發出無分支表單從 (x >= 0 && y >= 0) 到 (x | y) >= 0 ,從 (x != 0 && y != 0) 到 (x | y) != 0。
- @a74nh, @AndyJGraham and @swapnilGaikwad 對 Arm64 效能改進做出了貢獻(請參閱 Arm64 部分)。
- @DeepakRajendrakumaran 為 AVX-512 做出了貢獻(見AVX-512部分)。
- @SingleAccretion 為預覽版本1進行了72個拉取請求 72 PR contributions 其中有:
1.PR#72719 最佳化的記憶體載入/在強制轉換下儲存
2.PR#77238 和 PR#76139 是與 SSA 相關的改進
3.PR#78246 透過刪除 ADDR 節點簡化 JIT IR
4.PR#77990 最佳化固定儲存
雲原生
- PR#79709 刪除了非 GC 靜態欄位的幫助程式呼叫, PR#80969 最佳化了 GC 型別的靜態欄位。
- PR#80831 對單態案例實現將強制轉換到介面進行非虛擬化。
Arm64
Arm64 效能改進工作正在按計劃進行 Issue#77010。
- @AndyJGraham and @a74nh 實施了與 ldp 和 stp 相關的窺視孔最佳化 PR#77540
- @a74nh 在PR#73472, PR#77728, PR#78223, 和 PR#77888 中啟用‘If Conversion’
- @swapnilGaikwad 在條件選擇中使用零暫存器(csel) PR#78330
- @SwapnilGaikwad 在 PR#79550啟用 mneg ,多選擇中的一項 (Issue#68028)
- 透過比較PR#75864 和 PR#75999得出更快的向量
- PR#75823 新增了對 Arm64 上的“移位暫存器”操作的支援
AVX-512
- .NET 8 將按計劃支援 AVX-512 ISA 擴充套件 Issue#77034.
- PR#76642 實現了 API, 公開Issue#73262中Vector512<T> 型別
- 虛擬機器中新增 AVX-512 狀態已透過 @DeepakRajendrakumaran 的同意收到支援 PR#74113
- @DeepakRajendrakumaran 新增了對emitOutput 輸出 路徑的EVEX 編碼支援PR#75934, PR#77419 和 PR#78044
- JitInterface 已由@DeepakRajendrakumaran 更新為Vector512 PR#81197
一般SIMD改進
- PR#77562 為在 Issue#76593 定義的 Vector64/128/256/512<T> 和 Vector<T>上新批准的 API 實施了額外的內部函式
- PR#79720 使用 HWIntrinsics 實現 Vector2/3/4 和 Vector<T>
- PR#77947 為 OrdinalIgnoreCase 向量化 String.Equals
PGO
PGO 的基本改進正在按計劃進行中 Issue#74873。
- 引入了新的 JIT 層,以僅檢測熱 Tier0 和 R2R 程式碼。這意味著您不再需要禁用 ReadyToRun 並犧牲啟動時間來獲得完全 PGO 級別的效能優勢: PR#70941
- PR#80481 為所有場景啟用了基於邊緣的配置檔案
- 構建預測列表已移至 JIT 的早期階段:
PR#80625, PR#80856, PR#81288, PR#81246, PR#81196, PR#81000, 和 PR#80891。
迴圈最佳化
- PR#75140 在迴圈克隆中支援委託 GDV guards
- PR#80353 擴充套件迴圈展開最佳化
一般最佳化
@SingleAccretion 在PR#76263 Long中啟用了32 位解鎖欄位註冊上的多註冊變數提升。
- PR#77103 實施了 Issue#8795中提出的新尾部合併最佳化
- PR#81055 確保 Span<T>.Length 和 ROSpan<T>.Length 被識別為“never negative”
- PR#79346 新增了一個早期的活躍度傳遞,允許 JIT 在傳遞結構引數時刪除大量不必要的結構副本
- PR#77874 刪除了一些涉及小整數型別的簡單操作的不必要的零/符號擴充套件指令
- 字串文字、typeof()、靜態欄位透過 PR#49576, PR#75573和 PR#76112
1.允許 JIT 在某些情況下省略 GC 寫障礙 PR#76135
2.typeof(..) 在大多數情況下不再需要助手呼叫,例如:
Type GetMyType() => typeof(string);
; Method MyType():System.Type:this
3.4883EC28 sub rsp, 40
4.48B918083857FC7F0000 mov rcx, 0x7FFC57380818
5.E80DE8AB5F call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
6.90 nop
7.4883C428 add rsp, 40
8.48B8B800000364020000 mov rax, 0x264030000B8 ; ‘System.String’ C3 ret -; Total bytes of code: 25 +; Total bytes of code: 11
- 靜態和靜態只讀欄位的一批改
進 PR#77102, PR#77593, PR#77354, PR#77737, PR#78593, PR#78736 and PR#78783
- PR#81005 中顯示的表示式就是一個很好的例子。JIT 現在能夠在.NET 8 中摺疊使用
JIT 吞吐量改進
- PR#80265 將 JitHashTable 迭代轉換為基於範圍的迭代for,將吞吐量提高了 0.22%
總之,.NET 8 預覽版1的釋出是 Microsoft 多元化工程師團隊與高度參與的開源社群之間良好協作的證明。.NET 8 中的新功能和改進是社群成員辛勤努力和奉獻的成果,我們非常感謝大家做出的貢獻。
該社群重視包容性和多樣性,能成為其中的一員,我們很自豪。我們致力於建立一個人人都可以訪問的技術生態系統。我們相信,只要我們一起努力,就可以取得偉大的勝利,我們對 .NET 的未來充滿期待。