Heute kündigen wir .NET Core 3.0 Preview 6 an . Es enthält Updates zum Kompilieren von Assemblys für einen verbesserten Start und zur Optimierung der Größe von Anwendungen mit Linker- und EventPipe-Verbesserungen. Wir haben auch neue Docker-Images für Alpine auf ARM64 veröffentlicht.

WPF- und Windows Forms-Update
Das WPF-Team hat nun die Veröffentlichung des größten Teils der WPF-Codebasis auf GitHub abgeschlossen . Tatsächlich haben sie gerade eine Quelle für fünfzehn Versammlungen veröffentlicht . Für alle, die mit WPF vertraut sind, sollten die Baugruppennamen sehr vertraut sein.
In einigen Fällen befinden sich noch Tests im Rückstand, um bei oder vor 3.0 GA veröffentlicht zu werden. Das Vorhandensein dieses gesamten Codes sollte es der WPF-Community jedoch ermöglichen, sich uneingeschränkt an Änderungen in WPF zu beteiligen. Aus dem Lesen einiger GitHub-Probleme geht hervor, dass die Community über einen eigenen Rückstand verfügt, auf dessen Realisierung sie gewartet hat. Dunkles Thema vielleicht?
Alpine Docker Bilder
Docker-Images sind jetzt sowohl für .NET Core als auch für ASP.NET Core auf ARM64 verfügbar. Sie waren bisher nur für x64 verfügbar.
Die folgenden Bilder können in einer Dockerfile
oder mit docker pull
, wie unten gezeigt:
docker pull mcr.microsoft.com/dotnet/core/runtime:3.0-alpine-arm64v8
docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine-arm64v8
Verbesserungen der Ereignisleitung
Event Pipe unterstützt jetzt mehrere Sitzungen. Dies bedeutet, dass Sie Ereignisse mit EventListener in-proc konsumieren und gleichzeitig nicht prozessbedingte Event-Pipe-Clients haben können.
Neue Perf Counters hinzugefügt:
- % Zeit in GC
- Gen 0 Heap Size
- Gen 1 Heap Size
- Gen 2 Heap Size
- LOH Heap Size
- Zuteilungsrate
- Anzahl der geladenen Baugruppen
- Anzahl der ThreadPool-Threads
- Überwachungssperrkonfliktrate
- ThreadPool Work Items Queue
- ThreadPool-Rate abgeschlossener Arbeitselemente
Profiler Attach wird jetzt mit derselben Event Pipe-Infrastruktur implementiert.
Unter Spielen mit Zählern von David Fowler erhalten Sie eine Vorstellung davon, was Sie mit Event Pipe tun können, um Ihre eigenen Leistungsuntersuchungen durchzuführen oder einfach den Anwendungsstatus zu überwachen.
Informationen zum Installieren des Dotnet-Zählertools finden Sie unter Punktnetzzähler.
Optimieren Sie Ihre .NET Core-Apps mit ReadyToRun-Images
Sie können die Startzeit Ihrer .NET Core-Anwendung verbessern, indem Sie Ihre Anwendungsassemblys im ReadyToRun-Format (R2R) kompilieren. R2R ist eine Form der AOT-Kompilierung.
R2R-Binärdateien verbessern die Startleistung, indem sie den Arbeitsaufwand reduzieren, den die JIT beim Laden Ihrer Anwendung leisten muss. Die Binärdateien enthalten ähnlichen nativen Code wie die JIT, wodurch die JIT ein bisschen Urlaub bekommt, wenn die Leistung am wichtigsten ist (beim Start). R2R-Binärdateien sind größer, da sie sowohl IL-Code (Intermediate Language) enthalten, der für einige Szenarien noch benötigt wird, als auch die native Version desselben Codes, um den Start zu verbessern.
R2R wird mit .NET Core 3.0 unterstützt. Es kann nicht mit früheren Versionen von .NET Core verwendet werden.
Beispielleistungszahlen
Im Folgenden sind die Leistungszahlen aufgeführt, die mit einer Beispiel-WPF-Anwendung erfasst wurden. Die Anwendung wurde als eigenständig veröffentlicht und verwendete nicht den Assembly-Linker (der später in diesem Beitrag behandelt wird).
Nur-IL-Anwendung:
- Startzeit: 1,9 Sekunden
- Speichernutzung: 69,1 MB
- Anwendungsgröße: 150 MB
Mit ReadyToRun-Bildern:
- Startzeit: 1,3 Sekunden.
- Speichernutzung: 55,7 MB
- Anwendungsgröße: 156 MB
ReadyToRun-Bilder, erklärt
Sie können R2R sowohl Bibliotheken als auch Anwendungsbinärdateien kompilieren. Derzeit können Bibliotheken nur als Teil einer Anwendung R2R-kompiliert werden, nicht als NuGet-Paket. Wir möchten mehr Feedback darüber, ob dieses Szenario wichtig ist.
AOT-Kompilierungsassemblys sind seit langem als Konzept für .NET verfügbar und gehen auf .NET Framework und NGEN zurück . NGEN hat einen entscheidenden Nachteil: Die Kompilierung muss auf Client-Computern mit dem NGEN-Tool durchgeführt werden. Es ist nicht möglich, NGEN-Images als Teil Ihres Anwendungsbuilds zu generieren.
Geben Sie .NET Core ein. Es wird mit crossgen geliefert , das native Bilder in einem neueren Format namens ReadyToRun erzeugt . Der Name beschreibt sein primäres Wertversprechen: Diese nativen Images können als Teil Ihres Builds erstellt werden und sind ohne zusätzliche Arbeit auf Client-Computern "betriebsbereit". Das ist eine große Verbesserung und auch ein wichtiger Gewinn für den Klimawandel.
In Bezug auf die Kompatibilität ähneln ReadyToRun-Images IL-Assemblys mit einigen wesentlichen Unterschieden.
- IL-Assemblys enthalten nur IL-Code . Sie können zu jeder Laufzeit ausgeführt werden, die das angegebene Zielframework für diese Assembly unterstützt. Beispielsweise kann eine
netstandard2.0
Assembly unter .NET Framework 4.6+ und .NET Core 2.0+ unter jedem unterstützten Betriebssystem (Windows, macOS, Linux) und jeder Architektur (Intel, ARM, 32-Bit, 64-Bit) ausgeführt werden. - R2R-Assemblys enthalten IL und nativen Code. Sie werden für eine bestimmte minimale .NET Core-Laufzeitversion und Laufzeitumgebung (RID) kompiliert. Beispielsweise kann eine
netstandard2.0
Assembly R2R für .NET Core 3.0 und Linux x64 kompiliert werden. Es kann nur in dieser oder einer kompatiblen Konfiguration (wie .NET Core 3.1 oder .NET Core 5.0 unter Linux x64) verwendet werden, da es nativen Code enthält, der nur in dieser Laufzeitumgebung verwendet werden kann.
Anleitung
Die ReadyToRun-Kompilierung ist eine reine Veröffentlichungsoption. Wir haben eine Vorschau-Version mit .NET Core 3.0 Preview 5 veröffentlicht.
Um die ReadyToRun-Kompilierung zu aktivieren, müssen Sie:
- Setzen Sie die
PublishReadyToRun
Eigenschaft auf true
. - Veröffentlichen Sie mit einem expliziten
RuntimeIdentifier
.
Hinweis: Wenn die Anwendungsassemblys kompiliert werden, ist der erzeugte native Code plattform- und architekturspezifisch (weshalb Sie beim Veröffentlichen einen gültigen RuntimeIdentifier angeben müssen).
Hier ist ein Beispiel:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <PublishReadyToRun>true</PublishReadyToRun> </PropertyGroup> </Project>
Und veröffentlichen Sie mit dem folgenden Befehl:
dotnet publish -r win-x64 -c Release
Hinweis: Der RuntimeIdentifier
kann auch in der Projektdatei festgelegt werden.
Hinweis: ReadyToRun wird derzeit nur für eigenständige Apps unterstützt . Es wird in einer späteren Vorschau für Framework-abhängige Apps aktiviert.
Die native Symbolgenerierung kann aktiviert werden, indem die PublishReadyToRunEmitSymbols
Eigenschaft in Ihrem Projekt auf true
. Sie müssen keine nativen Symbole für Debugging-Zwecke generieren. Diese Symbole sind nur für Profilierungszwecke nützlich.
Das SDK unterstützt derzeit eine Möglichkeit, bestimmte Assemblys von der Kompilierung in ReadyToRun-Images auszuschließen. Dies kann in Fällen nützlich sein, in denen bestimmte Baugruppen nicht wirklich für die Leistung optimiert werden müssen. Dies kann dazu beitragen, die Größe der Anwendung zu reduzieren. Dies kann auch eine nützliche Problemumgehung für Fälle sein, in denen der ReadyToRun-Compiler eine bestimmte Assembly nicht kompilieren kann. Der Ausschluss erfolgt über die Elementgruppe PublishReadyToRunExclude. Beispiel:
<ItemGroup> <PublishReadyToRunExclude Include="FilenameOfAssemblyToExclude.dll" /> </ItemGroup>
Plattformübergreifende / architektonische Zusammenstellungen
Der ReadyToRun-Compiler unterstützt derzeit kein Cross-Targeting. Sie müssen auf einem bestimmten Ziel kompilieren. Wenn Sie beispielsweise R2R-Images für Windows x64 möchten, müssen Sie den Veröffentlichungsbefehl in dieser Umgebung ausführen.
Ausnahmen hiervon:
- Windows x64 kann zum Kompilieren von Windows ARM32-, ARM64- und x86-Images verwendet werden.
- Windows x86 kann zum Kompilieren von Windows ARM32-Images verwendet werden.
- Linux x64 kann zum Kompilieren von Linux ARM32- und ARM64-Images verwendet werden.
Baugruppenverknüpfung
Das .NET Core 3.0 SDK enthält ein Tool, mit dem Sie die Größe von Apps reduzieren können, indem Sie IL analysieren und nicht verwendete Assemblys kürzen.
Mit .NET Core war es immer möglich, eigenständige Apps zu veröffentlichen, die alles enthalten, was zum Ausführen Ihres Codes erforderlich ist, ohne dass .NET auf dem Bereitstellungsziel installiert werden muss. In einigen Fällen benötigt die App nur eine kleine Teilmenge des Frameworks, um zu funktionieren, und kann möglicherweise erheblich verkleinert werden, indem nur die verwendeten Bibliotheken einbezogen werden.
Wir verwenden den IL-Linker , um die IL Ihrer Anwendung zu scannen, um festzustellen, welcher Code tatsächlich benötigt wird, und um dann nicht verwendete Framework-Bibliotheken zu kürzen. Dies kann die Größe einiger Apps erheblich reduzieren. In der Regel profitieren kleine werkzeugähnliche Konsolen-Apps am meisten, da sie in der Regel relativ kleine Teilmengen des Frameworks verwenden und sich normalerweise besser zuschneiden lassen.
Um dieses Tool zu verwenden, setzen Sie PublishTrimmed=true
in Ihrem Projekt und veröffentlichen Sie eine eigenständige App:
dotnet publish -r <rid> -c Release
Die Veröffentlichungsausgabe enthält eine Teilmenge der Framework-Bibliotheken, je nachdem, was der Anwendungscode aufruft. Bei einer Helloworld-App reduziert der Linker die Größe von ~ 68 MB auf ~ 28 MB.
Anwendungen oder Frameworks (einschließlich ASP.NET Core und WPF), die Reflektion oder verwandte dynamische Funktionen verwenden, werden beim Trimmen häufig unterbrochen, da der Linker dieses dynamische Verhalten nicht kennt und normalerweise nicht bestimmen kann, welche Framework-Typen für die Reflektion erforderlich sind zur Laufzeit. Um solche Apps zu kürzen, müssen Sie dem Linker alle Typen mitteilen, die durch Reflektion in Ihrem Code und in allen Paketen oder Frameworks, von denen Sie abhängig sind, benötigt werden. Testen Sie Ihre Apps nach dem Zuschneiden.
Weitere Informationen zum IL Linker finden Sie in der Dokumentation oder im Mono / Linker Repo.
Hinweis: In früheren Versionen von .NET Core wurde ILLink.Tasks als externes NuGet-Paket ausgeliefert und bot weitgehend die gleiche Funktionalität. Es wird nicht mehr unterstützt - bitte aktualisieren Sie auf das neueste 3.0 SDK und probieren Sie die neue Erfahrung aus!
Linker und ReadToRun zusammen verwenden
Der Linker und der ReadyToRun-Compiler können für dieselbe Anwendung verwendet werden. Im Allgemeinen verkleinert der Linker Ihre Anwendung, und der sofort einsatzbereite Compiler macht sie wieder etwas größer, jedoch mit einem erheblichen Leistungsgewinn. Es lohnt sich, in verschiedenen Konfigurationen zu testen, um die Auswirkungen der einzelnen Optionen zu verstehen.
Hinweis: dotnet / sdk # 3257 verhindert, dass der Linker und ReadyToRun zusammen für WPF- und Windows Forms-Anwendungen verwendet werden. Wir arbeiten daran, dies im Rahmen der .NET Core 3.0-Version zu beheben.
Native Hosting-Beispiel
Das Team hat kürzlich ein Native Hosting-Beispiel veröffentlicht . Es zeigt einen Best-Practice-Ansatz für das Hosten von .NET Core in einer nativen Anwendung.
Als Teil von .NET Core 3.0 stellen wir nun allgemeine Funktionen für native .NET Core-Hosts bereit, die zuvor nur für von .NET Core verwaltete Anwendungen über die offiziell bereitgestellten .NET Core-Hosts verfügbar waren. Die Funktionalität bezieht sich hauptsächlich auf das Laden von Baugruppen. Diese Funktionalität sollte es einfacher machen, native Hosts zu erstellen, die alle Funktionen von .NET Core nutzen können.
HTTP / 2-Unterstützung in HttpClient
HTTP / 2 ist eine wichtige Überarbeitung des HTTP-Protokolls. Einige der bemerkenswerten Funktionen von HTTP / 2 sind die Unterstützung der Header-Komprimierung und vollständig gemultiplexter Streams über dieselbe Verbindung. Während HTTP / 2 die Semantik von HTTP (HTTP-Header, -Methoden usw.) beibehält, ist es eine Änderung von HTTP / 1.x, wie Daten gerahmt und über das Kabel gesendet werden.
HttpClient
jetzt Unterstützung für HTTP / 2-Anforderungen. Während die Standardeinstellung HTTP / 1.1 bleibt, können Sie sich für die Verwendung von HTTP / 2 entscheiden, indem Sie die Version in Ihrer HTTP-Anforderungsnachricht festlegen.
var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };
Alternativ können Sie standardmäßig HTTP / 2-Anforderungen senden, indem Sie die DefaultRequestVersion
Eigenschaft in HttpClient
DefaultRequestVersion
.
var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001"), DefaultRequestVersion = new Version(2, 0) };
Infolge dieser Änderung des Framings müssen Server und Clients die verwendete Protokollversion aushandeln. Application-Layer Protocol Negotiation (ALPN) ist eine TLS-Erweiterung, mit der Server und Client die Protokollversion aushandeln können, die im Rahmen ihres TLS-Handshakes verwendet wird. Während es möglich ist, Vorkenntnisse zwischen dem Server und dem Client über das Protokoll zu haben, unterstützen die meisten Server nur ALPN als einzige Möglichkeit, eine HTTP / 2-Verbindung herzustellen. Daher wird HTTP / 2 von HttpClient
nur über eine TLS-Verbindung ausgehandelt.
In Entwicklungsszenarien, in denen Server und Client von vornherein wissen, dass beide unverschlüsselt HTTP / 2 sprechen, können Sie eine HTTP / 2-Verbindung über Klartext herstellen, indem Sie einen AppContext
Schalter oder eine Umgebungsvariable ( DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT=1
) DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT=1
.
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
Schließen
Bitte probieren Sie die neuen Funktionen aus. Bitte reichen Sie Probleme für die Fehler oder herausfordernden Erfahrungen ein, die Sie finden. Wir wollen das Feedback! Sie können auch Feature-Anfragen einreichen, aber diese müssen wahrscheinlich warten, bis sie bis zur nächsten Version implementiert werden.
Wir stehen kurz vor der Fertigstellung der Funktionen für .NET Core 3.0 und verlagern den Fokus des Teams jetzt auf die Qualität der Version. Wir haben ein paar Monate Zeit, um Fehler zu beheben und die Leistung zu verbessern. Wir freuen uns über Ihr Feedback, wenn wir diesen Prozess ebenfalls durcharbeiten.
In diesem Sinne werden wir bald die Hauptzweige von .NET Core-Repos auf die nächste Hauptversion umstellen, wahrscheinlich bei oder kurz nach der Preview 7-Version (Juli).
Vielen Dank, dass Sie die Vorschau von .NET Core 3.0 ausprobiert haben. Wir bedanken uns für Ihre Hilfe. An diesem Punkt konzentrieren wir uns darauf, eine endgültige Veröffentlichung in Ihre Hände zu bekommen.
Richard LanderPM, .NET-Team