.NET Core 2.1 Preview 1 釋出:更快的構建效能

類別: IT
.NET Core

原文: Announcing .NET Core 2.1 Preview 1

今天,我們宣佈釋出 .NET Core 2.1 Preview 1。這是 .NET Core 2.1的第一個公開發布。我們有很大的改進希望分享出來,並且渴望得到您的反饋意見,無論是在評論中還是在 github 中 dotnet/core #1297

ASP.NET Core 2.1 Preview 1和 Entity Framework 2.1 Preview 1也會在今天釋出。

您可以在 Windows,MacOS 和 Linux 上下載並開始使用 .NET Core 2.1 Preview 1:

  • .NET Core 2.1 Preview 1 SDK— 包含 Runtime

  • .NET Core 2.1 Preview 1 Runtime

您可以使用 Visual Studio 2017 15.6 Preview 6及更高版本或 Visual Studio Code 來開發 .NET Core 2.1 應用程式。我們預計 Visual Studio for Mac 將在 15.7 版本支援。

ASP.NET Core 2.1 預覽版不會自動部署到 Azure 應用服務。相應的,您可以通過一點點配置來實現部署到 Azure

Visual Studio Team Service 將在 .NET Core 2.1 RTM 釋出時支援。

您可以在.NET Core 2.1 Preview 1 發行說明中看到該發行版的完整詳細資訊。發行說明中包含已知問題和解決方法。

非常感謝幫助釋出的每個人。如果沒有你,我們不可能走到現在,當我們一起工作到 .NET Core 2.1 RTM 時,我們會繼續需要你的幫助。

現在讓我們來看看 .NET Core 2.1 Preview 1 釋出中的許多改進。與 .NET Core 2.0一樣,它的發行版本很大,你會找到多項改進措施,以便讓你升級。

主題

.NET Core 2.1 的釋出旨在改進以下主題:

  • 更快的構建效能

  • 縮小 ASP.NET Core 和 EF Core 之間差距 (原文: Close gaps in ASP.NET Core and EF Core)

  • 改進與 .NET Framework 的相容性

  • GDPR 和安全

  • 微服務和Azure

  • 更強大的工程系統

這些主題的一些改進尚未在 Preview 1 中進行。這些主題會指引我們接下來的工作。

全域性工具

.NET Core 現在有一個新部署和擴充套件機制。這種新體驗與 NPM 全域性工具非常相似,並且受到 NPM 全域性工具的啟發。

使用以下命令,您可以使用我們釋出的名為 dotnetsay的示例工具自行嘗試 .NET Core 全域性工具(在您安裝 .NET Core 2.1 Preview 1 之後):

dotnet install tool -g dotnetsaydotnetsay

一旦你安裝了dotnetsay,你可以直接使用它,只需在你的命令提示符或終端中輸入dotnetsay即可。您可以關閉終端會話、在終端中切換驅動器、或者重新啟動機器,命令仍然在那裡。 dotnetsay 現在在你的 path 裡。檢查 %USERPROFILE%\.dotnet\tools 或~\.dotnet\tools 來檢視計算機上的工具安裝位置。

您可以通過檢視 donetsay 工具示例來建立自己的全域性工具。
You can create your own global tools by looking at the donetsay tools sample.

.NET Core 工具是 .NET Core 控制檯應用程式,它們是作為 NuGet 包打包和獲取的。預設情況下,這些工具是框架依賴的應用程式,並包含其所有的 NuGet 依賴項。這意味著預設情況下,給定的全域性工具將在任何作業系統或晶片架構上執行。假如您需要在新版本的 Linux 上使用現有工具,只要 .NET Core 在那裡工作,您應該能夠執行該工具。

目前,.NET Core Tools 僅支援全域性安裝,並且需要安裝-g引數。我們也在進行各種形式的本地安裝,但這些還沒有準備好在 Preview 1 中。

我們期望有一個全新的工具生態系統來為完善 .NET 自身。其中一些工具將專門針對 .NET Core 開發,其中許多工具將具有通用性。這些工具被部署到 NuGet。預設情況下,使用 dotnet tool install 在 NuGet.org 上查詢工具。

如果你對 dotnetay 很好奇,它是仿照 docker/whalesay的, 進一步是仿照 cowsay的。 dotnetsay 只是一個 dotnet-bot,他是我們最忙碌的開發人員之一!

構建效能優化

.NET Core 2.1 中的構建時效能得到了很大的提升,特別是對於增量構建。這些改進同時適用於命令列上的dotnet build 和 Visual Studio 中的構建。 我們對 CLI 工具和 MSBuild 進行了改進,以使這些工具提供更快的體驗。

下面的圖表提供了您可以從新版本中獲得的改進的具體數字。您可以看到 .NET Core 2.0,.NET Core 2.1 Preview 1 以及我們預期 .NET Core RTM 中會達到的數值。

您可以嘗試在 mikeharder/dotnet-cli-perf中自行構建相同的程式碼,你會得到類似的結果。請注意,這些改進是針對增量構建的,因此您只能在第二次構建之後看到好處。

次要版本前滾

您現在可以在相同主要版本範圍內的較新執行時版本上執行 .NET Core 應用程式。 例如,您將能夠在. NET Core 2.1 上執行 .NET Core 2.0 應用程式,或者在 .NET Core 2.5 上執行 .NET Core 2.1 應用程式(如果我們提供這種版本的話)。前滾行為僅適用於次要版本。例如,.NET Core 2.x 應用程式永遠不會自動前滾到 .NET Core 3.0 或更高版本。

如果預期的 .NET Core 版本可用,則使用它。 如果預期的 .NET Core 版本在給定的環境中不可用,則前滾行為僅與此相關。

您可以使用如下引數禁用次要版本前滾

  • 環境變數: DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=0

  • runtimeconfig.json: rollForwardOnNoCandidateFx=0

  • CLI: –roll-forward-on-no-candidate-fx=0

Sockets 效能和 HTTP 託管處理程式

我們對 .NET Core 2.1 中的 sockets 進行了重大改進。sockets 是傳出和傳入網路通訊的基礎。在 .NET Core 2.0 中,ASP.NET Kestrel Web 伺服器和 HttpClient 使用 native sockets,而不是 .NET Socket 類。我們正在改變這種狀況,取而代之的是在 .NET sockets 上建立更高層次的網路 API。

我們在 Preview 1 中對 sockets 做了三項重要的效能改進:

  • 支援 Socket/NetworkStream中的 Span/Memory

  • 改進了 Windows 和 Linux 上的效能, 這得益於各種修復(例如重用 PreAllocatedOverlapped、linux 上的快取操作物件、linux epoll 通知的改進排程等)

  • 改進了 SslStream 的效能, 以及支援 ALPN (HTTP2 所需) 和精簡 SslStream 設定。

對於 HttpClient,我們徹底重新構建了一個名為 SocketHttpHandler的託管 HttpClientHandler。正如你可能猜到的那樣,它是基於 .NET sockets 和 Span 的 HttpClient 的 C# 實現。

SocketHttpHandler 最大的勝利就是效能。它比現有的實現快得多。還有其他好處:

  • 消除對 libcurl(linux) 和 WinHTTP(Windows) 的平臺依賴性 - 簡化了開發、部署和服務

  • 跨平臺和平臺/依賴項版本的一致行為。(原文:Consistent behavior across platforms and platform/dependency versions)

在 Preview 1 中,您可以選擇使用以下方式之一來使用 SocketHTTPHandler:

  • 環境變數: COMPlus_UseManagedHttpClientHandler=true

  • AppContext: System.Net.Http.UseManagedHttpClientHandler=true

在 Preview 2 (或 GitHub master 分支) 中, 您將能夠按照您所希望的那樣去new一個處理程式: new HttpClient(new SocketsHttpHandler())。我們還考慮將新的處理程式設定為預設的, 並將現有的 native handler (基於 libcurl 和 WinHTTP) 作為可選的。

我們仍在努力將 Kestrel 遷移到 sockets。我們還沒有確定計劃來分享給大家,但您可以自行使用 Sockets 來測試 ASP.NET Core

您可能想知道在傳入和傳出場景之間如何共享 sockets 改進的, 因為它們感覺非常不同。其實很簡單。如果您是客戶端, 則在伺服器上進行連線。如果您是伺服器, 則偵聽並等待連線。一旦建立了連線, 資料就可以兩種方式流動, 這從效能的角度來看是至關重要的。因此, 這些 socket 改進應改善這兩種情況。

Span, Memory and friends

我們正在引入一組新的型別來更高效的使用陣列和其他型別的記憶體。它們包含在 Preview 1 中。今天,如果您想傳遞10,000元素陣列的前1000個元素,則需要複製這1000個元素並將該副本傳遞給呼叫者。這種操作在時間和空間上都很昂貴。新的 Span 型別使您可以提供該陣列的虛擬檢視,而無需時間或空間開銷。這也是一個 struct,這意味著沒有分配成本。

Span 和相關型別提供了來自眾多不同來源(如陣列,堆疊分配和原生程式碼)的統一記憶體表示。憑藉其分片功能,可以避免在許多情況下進行昂貴的複製和分配,如字串處理,緩衝區管理等,並且為不安全的程式碼提供了安全的替代方案。我們預計這些型別將在效能要求較高的場景中首先使用,但隨後會取代陣列,作為管理 .NET 中大型資料塊的主要方式。

就用法而言,您可以從陣列中建立一個Span :

var arr = new byte[10]; Span<byte> bytes = arr; // Implicit cast from T[] to Span<T>

通過使用 span 切片方法的過載, 您可以輕鬆高效地建立一個範圍來表示/指向此陣列的子集。從那裡, 您可以索引到結果範圍內, 以便在原始陣列的相關部分中寫入和讀取資料:

Span<byte> slicedBytes = bytes.Slice(start: 5, length: 2);slicedBytes[0] = 42;slicedBytes[1] = 43; Assert.Equal(42, slicedBytes[0]); Assert.Equal(43, slicedBytes[1]); Assert.Equal(arr[5], slicedBytes[0]); Assert.Equal(arr[6], slicedBytes[1]);slicedBytes[2] = 44; // Throws IndexOutOfRangeException bytes[2] = 45; // OK Assert.Equal(arr[2], bytes[2]); Assert.Equal(45, arr[2]);

Jared Parsons 他的頻道9視訊中提供了一個很棒的介紹 C# 7.2: Understanding Span.
Stephen Toub 有更詳細的介紹在這個文章裡 C# – All About Span: Exploring a New .NET Mainstay.

Windows Compatibility Pack

將現有程式碼從 .NET Framework 中移植到 .NET Core 時, 可以使用新的 Windows 相容性包。與 .NET Core 中提供的內容相比, 它提供了額外的 20000 個 API。這包括System.Drawing, EventLog, WMI, 效能計數器和 Windows 服務。

下面的示例演示如何使用 Windows 相容性包提供的 API 訪問 windows 登錄檔。

private static string GetLoggingPath() { // Verify the code is running on Windows. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))    { using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Fabrikam\AssetManagement"))        { if (key?.GetValue("LoggingDirectoryPath") is string configuredPath) return configuredPath;        }    } // This is either not running on Windows or no logging path was configured, // so just use the path for non-roaming user-specific data files. var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); return Path.Combine(appDataPath, "Fabrikam", "AssetManagement", "Logging");}

平臺支援

我們期望為 .NET Core 2.1 支援以下作業系統

  • Windows Client: 7, 8.1, 10 (1607+)

  • Windows Server: 2008 R2 SP1+

  • macOS: 10.12+

  • RHEL: 7+

  • Fedora: 26+

  • openSUSE: 42.3+

  • Debian: 8+

  • Ubuntu: 14.04, 16.04, 17.10+

  • SLES: 12+

  • Alpine: 3.6+

Docker

對於 Docker, 在 microsoft/dotnet上我們相對於 2.0 做了一些修改:

  • 新增了 Alpine runtime 和 SDK 映象 (x64).

  • 新增了 Ubuntu Bionic/18.04, 用於 runtime 和 SDK 映象 (x64 and ARM32).

  • 從 debian:stretch 切換到 debian:stretch-slim 的 runtime 映象. (x64 and ARM32).

  • 放棄 debian:jessie (runtime and SDK).

這些變化在某種程度上是基於我們在過去六個月中聽到的兩個重複的反饋資訊:

  • 提供更小的映象,尤其是 runtime

  • Provide images with less surface area and/or more frequently updated (than Debian), from a vulnerability standpoint.

我們還重寫了 .NET Core Docker 示例的說明和程式碼。
這些示例提供了更好的說明,並實現了更多場景,如單元測試和使用 docker registries。 我們希望您找到有用的示例,並且我們計劃繼續擴充套件它們。 告訴我們您希望我們新增哪些內容以使 .NET Core 和 Docker 更好地協同工作

尾聲

感謝您嘗試 .NET Core 2.1 Preview 1. 請嘗試在現有的應用程式中使用 .NET Core 2.1 Preview 1,並且請試用本文介紹的新功能。 我們已經付出了很多努力使它們更好,但我們需要您的反饋讓它們跨過終點線,以便最終釋出。

再一次感謝所有為釋出做出貢獻的人。 我們非常感謝您提供的所有問題和PR,這些都有助於提供此首次預覽版。

.NET Core 2.1 Preview 1 釋出:更快的構建效能原文請看這裡