Microsoft .NET est le nom donné à un ensemble de produits et de technologies informatiques de l'entreprise Microsoft pour rendre des applications facilement portables sur Internet. .NET 6 RC1 a été testé et est pris en charge par la Preview 4 de Visual Studio 2022. Dans la version 6 de .NET, les diagnostics du cloud ont été améliorés avec dotnet monitor et OpenTelemetry. La prise en charge de WebAssembly est plus performante. De nouvelles API ont été ajoutées, pour HTTP/3, le traitement de JSON, les mathématiques et la manipulation directe de la mémoire.
Voici, ci-dessous, quelques-unes des améliorations apportées à .NET 6 :
Une plateforme unifiée et étendue
.NET 6 offre une plateforme unifiée, pour les applications web, cloud, de bureau, d'IoT et mobiles. La plateforme sous-jacente a été mise à jour pour répondre aux besoins de tous les types d'applications et pour faciliter la réutilisation du code dans toutes les applications. Les nouvelles capacités et améliorations sont disponibles pour toutes les applications en même temps, de sorte qu’un code exécuté dans le cloud ou sur un appareil mobile se comporte de la même manière et bénéficie des mêmes avantages.
La portée des développeurs .NET continue de s'élargir à chaque version. L'apprentissage automatique et WebAssembly sont deux des ajouts les plus récents. Par exemple, avec l'apprentissage automatique, il est possible d’écrire des applications qui recherchent des anomalies dans les données en continu. Avec WebAssembly, il est possible d’héberger des applications .NET dans le navigateur, tout comme HTML et JavaScript, ou les combiner avec HTML et JavaScript.
L'un des ajouts les plus intéressants est l'interface utilisateur multiplateforme de .NET (.NET MAUI). Il est désormais possible d’écrire du code dans un seul projet qui offre une expérience d'application client moderne sur les systèmes d'exploitation mobiles et de bureau. .NET MAUI sera publié un peu plus tard que .NET 6.
Contrôle et casting plus rapides d'interface
Les performances de casting d'interface ont été améliorées de 16 % à 38 %. Cette amélioration est particulièrement utile pour la correspondance de modèle de C# vers et entre les interfaces. Le graphique ci-dessous illustre l'ampleur de l'amélioration pour un benchmark représentatif.
L'un des principaux avantages du passage de certaines parties du moteur d'exécution de .NET de C++ à C# géré est qu'il réduit la barrière à la contribution. Cela inclut le casting d'interface, qui a été déplacé vers C# lors d'un changement précoce de .NET 6. Beaucoup plus de personnes dans l'écosystème .NET maîtrisent le C# que le C++ (et le runtime utilise des modèles C++ difficiles). Le simple fait de pouvoir lire une partie du code qui compose le moteur d'exécution est une étape importante pour développer la confiance dans la contribution sous ses différentes formes.
Arm64
L’équipe de développement de .NET a ajouté le support initial pour Arm64 avec .NET Core 3.0 et Arm32 avant cela. L'équipe a fait des investissements majeurs dans Arm64 dans chacune des dernières versions. Dans .NET 6, elle s’est principalement concentrée sur la prise en charge des nouvelles puces Apple Silicon et du scénario d'émulation x64 sur les systèmes d'exploitation macOS et Windows Arm64.
« L'Arm64 suscite beaucoup d'enthousiasme en ce moment, que ce soit pour les ordinateurs portables, le matériel informatique et d'autres appareils. Nous ressentons cette même excitation au sein de l'équipe .NET et faisons de notre mieux pour suivre cette tendance industrielle. Nous collaborons directement avec les ingénieurs d'Arm Holdings, d'Apple et de Microsoft pour nous assurer que nos implémentations sont correctes et optimisées, et que nos plans s'alignent. Ces partenariats étroits nous ont beaucoup aidés », souligne Richard Lander.
Il est possible d’installer les versions Arm64 et x64 de .NET sur les systèmes d'exploitation macOS 11+ et Windows 11+ Arm64. Pour parvenir à ce résultat, l’équipe de développement de .NET a dû faire plusieurs choix de conception et modifier ses produits pour que cela fonctionne. Par défaut, si une application .NET 6 est exécutée avec le SDK Arm64, elle s'exécutera en Arm64. Il est possible de passer facilement à l'exécution en x64 avec l'argument -a, comme dotnet run -a x64. Le même argument fonctionne pour les autres CLI.
Lorsque -a x64 est utilisé, le SDK s'exécute toujours de manière native en Arm64. Il existe des points fixes dans l'architecture du SDK .NET où les limites de processus existent. La plupart du temps, un processus doit être tout Arm64 ou tout x64. En réalité, le .NET CLI attend la dernière création de processus dans l'architecture du SDK et lance celui-ci comme l'architecture de puce qui a été demandée, comme x64. C'est dans ce processus que le code s'exécute. De cette façon, le développeur bénéficie des avantages de l'Arm64 en tant que développeur, mais le code s'exécute dans le processus dont il a besoin. Ceci n'est pertinent que s’il a besoin d'exécuter du code en x64. Si ce n'est pas le cas, il est tout simplement possible de tout exécuter en Arm64 tout le temps.
Windows Arm64
Microsoft dispose d'un outil simple qui démontre l'environnement sur lequel tourne .NET.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | C:Usersrich>dotnet tool install -g dotnet-runtimeinfo You can invoke the tool using the following command: dotnet-runtimeinfo Tool 'dotnet-runtimeinfo' (version '1.0.5') was successfully installed. C:Usersrich>dotnet runtimeinfo 42 42 ,d ,d 42 42 42 ,adPPYb,42 ,adPPYba, MM42MMM 8b,dPPYba, ,adPPYba, MM42MMM a8" `Y42 a8" "8a 42 42P' `"8a a8P_____42 42 8b 42 8b d8 42 42 42 8PP""""""" 42 "8a, ,d42 "8a, ,a8" 42, 42 42 "8b, ,aa 42, `"8bbdP"Y8 `"YbbdP"' "Y428 42 42 `"Ybbd8"' "Y428 **.NET information Version: 6.0.0 FrameworkDescription: .NET 6.0.0-rtm.21522.10 Libraries version: 6.0.0-rtm.21522.10 Libraries hash: 4822e3c3aa77eb82b2fb33c9321f923cf11ddde6 **Environment information ProcessorCount: 8 OSArchitecture: Arm64 OSDescription: Microsoft Windows 10.0.22494 OSVersion: Microsoft Windows NT 10.0.22494.0 |
L'outil fonctionne en mode natif sur Windows Arm64. Voici, ci-dessous, le résultat en ASP.NET Core.
Performances de l'Arm64
Les projets de prise en charge d'Apple Silicon et de l'émulation x64 étaient très importants, mais les performances de l'Arm64 ont également été améliorées. L’image ci-dessous montre une amélioration de la mise à zéro du contenu des cadres de pile, qui est une opération courante. La ligne verte représente le nouveau comportement, tandis que la ligne orange représente une autre expérience (moins avantageuse), toutes deux améliorées par rapport à la ligne de base, représentée par la ligne bleue. Pour ce test, plus bas est mieux.
PGO dynamique
Le Dynamic Profile-guided Optimization (PGO) ou encore l'optimisation dynamique guidée par le profil peut améliorer sensiblement les performances en régime permanent. Par exemple, PGO permet une amélioration de 26 % (510K -> 640K) des requêtes par seconde pour la suite TechEmpower JSON "MVC". PGO dynamique s'appuie sur la compilation par niveaux, qui permet aux méthodes d'être d'abord compilées très rapidement (niveau 0) pour améliorer les performances au démarrage, puis d'être recompilées (niveau 1) avec de nombreuses optimisations une fois que la méthode s'est révélée efficace. Ce modèle permet d'instrumenter les méthodes au niveau 0 afin d'effectuer diverses observations sur l'exécution du code.
Lorsque ces méthodes sont réintroduites au niveau 1, les informations recueillies à partir des exécutions du niveau 0 sont utilisées pour mieux optimiser le code du niveau 1. C'est l'essence même du mécanisme. Les temps de démarrage de Dynamic PGO seront légèrement plus lents que ceux du runtime par défaut, car du code supplémentaire est exécuté dans les méthodes de niveau 0 pour observer le comportement de la méthode.
Pour activer PGO dynamique, il faut definir DOTNET_TieredPGO=1 dans l'environnement où l’application sera exécutée. Il faut également s’assurer que Tiered Compilation est activé (il l'est par défaut). Dynamic PGO est opt-in parce qu'il s'agit d'une technologie nouvelle et importante. Le PGO dynamique est pris en charge et est déjà utilisé en production par au moins un très grand service Microsoft.
Code : | Sélectionner tout |
1 2 3 4 | private IEnumerator<long> _source = Enumerable.Range(0, long.MaxValue).GetEnumerator(); [Benchmark] public void MoveNext() => _source.MoveNext(); |
Voici le résultat, avec et sans PGO dynamique :
C'est une différence assez importante, mais la taille du code a également augmenté, ce qui pourrait en surprendre plus d'un. Il s'agit de la taille du code d'assemblage généré par le JIT, et non des allocations de mémoire. Une optimisation courante dans les implémentations PGO est le « fractionnement chaud/froid », où les sections d'une méthode fréquemment exécutées ("chaudes" sont rapprochées au début de la méthode, et les sections d'une méthode rarement exécutées ("froides" sont déplacées à la fin de la méthode. Cela permet une meilleure utilisation des caches d'instructions et minimise les charges de code probablement inutilisé.
Comme contexte, la répartition d'interface est le type d'appel le plus coûteux dans .NET. Les appels de méthodes non virtuelles sont les plus rapides, et encore plus rapides sont les appels qui peuvent être éliminés par inlining. Dans ce cas, le PGO dynamique fournit deux sites d'appel (alternatifs) pour MoveNext. Le premier, le chaud, est un appel direct à Enumerable+RangeIterator.MoveNext et l'autre, le froid, est un appel à l'interface virtuelle via IEnumerator<int>. C'est une grande victoire si le chaud est appelé la plupart du temps.
Lorsque le JIT a instrumenté le code de niveau 0 pour cette méthode, il a notamment instrumenté cette répartition d'interface pour suivre le type concret de _source à chaque invocation. Et le JIT a trouvé que chaque invocation était sur un type appelé Enumerable+RangeIterator, qui est une classe privée utilisée pour implémenter Enumerable.Range à l'intérieur de l'implémentation Enumerable. En tant que tel, pour le niveau 1, le JIT a émis une vérification pour voir si le type de _source est ce Enumerable+RangeIterator : si ce n'est pas le cas, alors il saute à la section froide que a été précédemment mise en évidence qui effectue la répartition normale de l'interface. Mais si c'est le cas, ce qui, d'après les données de profilage, devrait être le cas dans la grande majorité du temps, il peut alors invoquer directement la méthode Enumerable+RangeIterator.MoveNext, non virtualisée. De plus, il a décidé qu'il était rentable de mettre en ligne cette méthode MoveNext. L'effet net est que le code assembleur généré est un peu plus gros, mais optimisé pour le scénario exact qui devrait être le plus courant.
Améliorations des entrées-sorties de fichiers
FileStream a été presque entièrement réécrit dans .NET 6, en mettant l'accent sur l'amélioration des performances des entrées-sorties de fichiers asynchrones. Sous Windows, l'implémentation n'utilise plus d'API bloquantes et peut être jusqu'à plusieurs fois plus rapide. Microsoft a également apporté des améliorations à l'utilisation de la mémoire, sur toutes les plateformes. Après la première opération asynchrone (qui alloue généralement la mémoire), l’équipe de développement de .NET a fait en sorte que les opérations asynchrones ne nécessitent aucune allocation. De plus, elle a uniformisé le comportement pour les cas limites où les implémentations Windows et Unix étaient différentes. Les améliorations de performance de cette réécriture profitent à tous les systèmes d'exploitation. Les utilisateurs de macOS et de Linux devraient également constater une amélioration significative des performances de FileStream. Le benchmark suivant écrit 100 Mo dans un nouveau fichier.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | private byte[] _bytes = new byte[8_000]; [Benchmark] public async Task Write100MBAsync() { using FileStream fs = new("file.txt", FileMode.Create, FileAccess.Write, FileShare.None, 1, FileOptions.Asynchronous); for (int i = 0; i < 100_000_000 / 8_000; i++) await fs.WriteAsync(_bytes); } |
Sous Windows avec un disque SSD, une accélération de 4 fois et une diminution de l'allocation de plus de 1200 a été observée :
L’équipe de développement de .NET a également reconnu le besoin de fonctionnalités d'E/S de fichiers plus performantes : lectures et écritures simultanées, et E/S de type scatter/gather. Elle a introduit de nouvelles API dans les classes System.IO.File et System.IO.RandomAccess pour ces cas.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 | async Task AllOrNothingAsync(string path, IReadOnlyList<ReadOnlyMemory<byte>> buffers) { using SafeFileHandle handle = File.OpenHandle( path, FileMode.Create, FileAccess.Write, FileShare.None, FileOptions.Asynchronous, preallocationSize: buffers.Sum(buffer => buffer.Length)); // hint for the OS to pre-allocate disk space await RandomAccess.WriteAsync(handle, buffers, fileOffset: 0); // on Linux it's translated to a single sys-call! } |
L'exemple présente :
- l'ouverture d'un handle de fichier à l'aide de la nouvelle API File.OpenHandle ;
- pré-affectation de l'espace disque à l'aide de la nouvelle fonctionnalité Taille de pré-affectation ;
- écriture dans le fichier à l'aide de la nouvelle API Scatter/Gather IO.
La fonctionnalité Size de préallocation améliore les performances car les opérations d'écriture n'ont pas besoin d'étendre le fichier et il est moins probable que le fichier soit fragmenté. Cette approche améliore la fiabilité puisque les opérations d'écriture n'échoueront plus en raison d'un manque d'espace puisque l'espace a déjà été réservé. L'API Scatter/Gather IO réduit le nombre d'appels système requis pour écrire les données.
Sécurité
La sécurité a été considérablement améliorée dans .NET 6. Elle constitue toujours une priorité pour l'équipe, y compris la modélisation des menaces, la cryptographie et les mesures de défense en profondeur. Sous Linux, l’équipe de développement de .NET s’appuie sur OpenSSL pour toutes les opérations cryptographiques, y compris pour TLS (requis pour HTTPS). Sous macOS et Windows, elle s’appuie sur les fonctionnalités fournies par le système d'exploitation dans le même but. Avec chaque nouvelle version de .NET, elle doit souvent ajouter la prise en charge d'une nouvelle version d'OpenSSL. .NET 6 ajoute la prise en charge d'OpenSSL 3.
OpenSSL a annoncéle 21 septembre la disponibilité de la version 3.0 et le renouvellement de la Licence Apache-2.0, avec l'utilisation du nouveau module FIPS dans les projets de développement d'applications. « Après 3 ans de développement, 17 versions alpha, 2 versions bêta, plus de 7 500 commits et des contributions de plus de 350 auteurs différents, nous avons finalement publié OpenSSL 3.0 ! », a annoncé Matt Caswell sur le blog officiel dédié à la plateforme.
.NET 6 requiert OpenSSL 1.1 ou plus et préférera la plus haute version installée d'OpenSSL qu'il peut trouver, jusqu'à et y compris la v3. Dans le cas général, l’utilisation d’OpenSSL 3 commencera probablement lorsque la distribution Linux utilisée l'adoptera par défaut. La plupart des distributions ne l'ont pas encore fait. Par exemple, l’installation de .NET 6 sur Red Hat 8 ou Ubuntu 20.04, ne permet pas (au moment de la rédaction de cette news ) d’utiliser OpenSSL 3.
L’équipe de développement de .NET a également publié une nouvelle feuille de route sur l'atténuation de la sécurité des runtime. Il est important que le moteur d'exécution utilisé soit à l'abri des attaques de type manuel. Dans .NET 6, elle a construit les premières implémentations de W^X et de la technologie Intel Control-flow enforcement (CET).
CET
La technologie CET (Control-flow Enforcement Technology) d'Intel est une fonction de sécurité disponible dans certains processeurs Intel et AMD récents. Elle ajoute des capacités au matériel qui protègent contre certains types d'attaques courantes impliquant le détournement du flux de contrôle. Avec les piles fantômes CET, le processeur et le système d'exploitation peuvent suivre le flux de contrôle des appels et des retours dans un thread dans la pile fantôme en plus de la pile de données, et détecter les modifications involontaires du flux de contrôle. La pile fantôme est protégée contre les accès à la mémoire du code d'application et permet de se défendre contre les attaques impliquant la programmation orientée retour (ROP).
En début d’année, Google Chrome et Microsoft Edgeont annoncé qu’ils prendront en charge la fonction de sécurité CET d'Intel, pour maintenir la sécurité et prévenir des vulnérabilités. Elle est conçue pour protéger les données des utilisateurs contre les attaques de la programmation orientée retour (ROP) et de la programmation orientée saut (JOP). Ces attaques de type ROP et JOP sont dangereuses et particulièrement difficiles à détecter ou à prévenir, car elles modifient le comportement normal d’un programme pour exécuter le code malveillant. Intel a collaboré activement avec Microsoft et d'autres partenaires industriels pour lutter contre ces types d’attaques en utilisant la technologie CET comme complément aux précédentes solutions implémentées.
Avec ROP, le cybercriminel s'appuie sur l'instruction RET (return) pour assembler un flux de code malveillant, récupère l'adresse de l'instruction suivante dans la pile et exécute les instructions à partir de cette adresse. Dans le cas d'attaques basées sur des ROP, l'acteur de la menace recherche a priori l'exécution d'une séquence d'octets dans le code du programme existant en analysant le programme sur le disque ou en mémoire. Windows 10 prend en charge la fonction de sécurité CET d'Intel grâce à un exécutable appelé Hardware-enforced Stack Defense. Dans un tweet, Johnathan Norman, le responsable de l'étude des vulnérabilités de Microsoft Edge, a laissé entendre que Microsoft Edge 90 prend en charge la technologie CET d'Intel dans les procédures sans moteur de rendu
W^X
W^X est l'une des mesures d'atténuation les plus fondamentales. Elle bloque le chemin d'attaque le plus simple en empêchant les pages de mémoire d'être accessibles en écriture et exécutables en même temps. L'absence de cette mesure d'atténuation nous a conduit à ne pas envisager des mesures d'atténuation plus avancées, car elles pourraient être contournées par l'absence de cette capacité. Avec W^X en place, Microsoft ajoute d'autres mesures d'atténuation complémentaires, comme CET.
Apple a rendu W^X obligatoire pour les futures versions du système d'exploitation de bureau macOS dans le cadre de la transition Apple Silicon. « Cela nous a motivés à programmer la mise en œuvre de cette mesure d'atténuation pour .NET 6, sur tous les systèmes d'exploitation pris en charge. Notre principe est de traiter tous les systèmes d'exploitation supportés de la même manière en matière de sécurité, dans la mesure du possible », déclare Microsoft. W^X est disponible sur tous les systèmes d'exploitation avec .NET 6 mais n'est activé par défaut que sur Apple Silicon. Il sera activé sur tous les systèmes d'exploitation dans .NET 7.
Containers Windows
.NET 6 apporte la prise en charge des containers Windows isolés des processus. Si des conteners Windows sont utilisés dans Azure Kubernetes Service (AKS), Il s’agit des conteners à processus isolé. Les conteneurs à processus isolé peuvent être considérés comme très similaires aux conteneurs Linux. Les conteneurs Linux utilisent des cgroups et les conteneurs Windows à processus isolés utilisent des Job Objects. Windows propose également les conteneurs Hyper-V, qui offrent une plus grande isolation grâce à une plus grande virtualisation. Il n'y a pas de changement dans .NET 6 pour les conteners Hyper-V.
La valeur principale de ce changement est que Environment.ProcessorCount rapportera maintenant la valeur correcte avec les conteners Windows isolés des processus. Si un conteneur à 2 cœurs est créé sur une machine à 64 cœurs, Environment.ProcessorCount indiquera 2. Dans les versions antérieures, cette propriété indiquait le nombre total de processeurs sur une machine, indépendamment de la limite spécifiée par le CLI de Docker, Kubernetes ou tout autre orchestrateur/exécutant de conteners. Cette valeur est utilisée par diverses parties de .NET à des fins de mise à l'échelle, notamment le ramasseur miettes de .NET (bien qu'il s'appuie sur une API connexe de niveau inférieur). Les bibliothèques communautaires s'appuient également sur cette API pour la mise à l'échelle.
Source : Microsoft
Et vous ?
Que pensez-vous des améliorations apportées par .NET 6 ?
Voir aussi :
Microsoft a publié la version stable de Visual Studio 2022 avec une nouvelle expérience de rechargement à chaud pour les applications natives C++, cette version est disponible uniquement en 64 bits
Google Chrome et Microsoft Edge prendront en charge la fonction de sécurité CET d'Intel, pour maintenir la sécurité et prévenir des vulnérabilités
OpenSSL annonce la disponibilité de la version 3.0 et le renouvellement de la Licence Apache-2.0, avec l'utilisation du nouveau module FIPS dans les projets de développement d'applications
Microsoft annonce la sortie de la première release candidate de .NET 6, disponible pour Linux, macOS et Windows, elle résout les problèmes fonctionnels et les régressions des fonctionnalités