.NET 6 est sorti - La version la plus rapide à ce jour

9
25
déc.
2021
Microsoft

La dernière version du cadriciel libre (sous licence MIT) et multiplateforme est apparue le 9 novembre 2021. C’est une version majeure, avec énormément de nouveautés et comme toujours des performances améliorées. Voyons ensemble pourquoi ce cadriciel est si apprécié.

La version 6 de .Net représente un an d’efforts. Elle apporte son lot d’améliorations du langage, des performances ainsi que la première prise en charge de manière native des processeurs Apple Silicon (Arm64). Elle dispose aussi :

Sommaire

Introduction

.NET 6 est le résultat d’un peu plus d’un an d’efforts de la part de l’équipe .NET et de la communauté. C# 10 et F# 6 apportent des améliorations au langage qui rendent votre code plus simple et meilleur. Comme pour chaque nouvelle version, il y a des améliorations énormes de performance.
Par ailleurs, .NET 6 est la première version qui prend en charge de manière native l'Apple Silicon (Arm64) et a également été améliorée pour Windows Arm64. Nous avons construit un nouveau système d’optimisation dynamique, guidée par le profil (Profil Guided Optimization) qui offre des optimisations importantes impossibles à mettre en œuvre avec la compilation à la volée traditionnelle (JIT).
Les diagnostics dans le cloud ont été améliorés au travers de OpenTelemetry et des dernières évolutions de dotnet monitor. La prise en charge de WebAssembly est plus performante. De nouvelles API ont été ajoutées, pour HTTP/3, le traitement du JSON, les mathématiques et la manipulation directe de la mémoire. .NET 6 est une version majeure et ainsi sera pris en charge pendant trois ans. Les développeurs ont déjà commencé à mettre à niveau leurs applications vers .NET 6 (NdT: comme votre serviteur) et les premiers résultats obtenus en production sont excellents.
.NET 6 est prêt pour votre application.

Vous pouvez télécharger .NET 6 pour Linux, macOS, et Windows.

Visual Studio 2022 est aussi désormais disponible. (NdT : pour les gens n’utilisant pas Windows, il y a notamment Visual Studio Code ou Rider de JetBrains). NdM: Visual Studio et Visual Studio Code sont des logiciels propriétaires basés sur le code libre VSCode (et VSCodium la version sans télémétrie). Rider est un logiciel propriétaire.

PowerShell 7.2, basé sur .NET 6, est également disponible. Les utilisateurs de PowerShell ont accès aux mêmes améliorations de performance et API que les développeurs .NET.
Pour rappel, PowerShell Core est un outil et un cadre d’automatisation et de configuration multiplateforme (Windows, Linux et macOS) qui fonctionne bien avec vos outils existants et qui est optimisé pour traiter les données structurées (par exemple, JSON, CSV, XML, etc.), les API REST et les modèles objets. Il comprend un interpréteur de ligne de commande, un langage de script associé et un cadriciel pour le traitement des cmdlets.

Si vous préférez découvrir les dernières fonctionnalités de .NET 6 à l’aide d’une discussion approfondie ou en vidéo, les conversations d’ingénieur à ingénieur sont disponibles, ainsi que la .NET Conf.

Les points clés

.NET 6 est :

Cette nouvelle version inclut environ dix mille commits git. Malgré la longueur de cet article, il passe sous silence de nombreuses améliorations. Vous devrez télécharger et essayer .NET 6 pour voir toutes les nouveautés.

Prise en charge

.NET 6 est une version LTS (Long-term Support) qui sera prise en charge pendant trois ans. Elle est prise en charge sur plusieurs systèmes d’exploitation, notamment macOS Apple Silicon, Debian, Ubuntu, Alpine Linux, CentOS, OpenSUSE, RHEL, Fedora, et SLES, ainsi que Windows.
Red Hat prend en charge .NET sur Red Hat Enterprise Linux, en collaboration avec l’équipe .NET. Sur RHEL 8 et plus, .NET 6 sera disponible pour les architectures AMD et Intel (x64_64), ARM (aarch64), ainsi que IBM Z et LinuxONE (s390x).
Veuillez commencer à migrer vos applications .NET vers .NET 6, en particulier les applications .NET 5. Les premiers retours utilisateurs nous ont indiqué que la mise à niveau vers .NET 6 était simple à partir de .NET Core 3.1 ou .NET 5.
.NET 6 est pris en charge par Visual Studio 2022 et Visual Studio 2022 pour Mac. .NET 6 est pris en charge aussi avec l’extension Visual Studio Code pour C#.

Azure App Service

Remarque : si votre application exécute déjà une version .NET 6 Preview ou RC sur App Service, elle sera mise à jour automatiquement au premier redémarrage une fois que le moteur d’exécution et le SDK .NET 6 seront déployés dans votre région. Si vous avez déployé une application autonome, vous devrez la recompiler et la redéployer.

Une plateforme unifiée et étendue

Plateforme unifiée
.NET 6 offre une plateforme unifiée, pour les applications de navigateur, de 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’apps et pour faciliter la réutilisation du code dans toutes vos apps. Les nouvelles capacités et améliorations sont disponibles pour toutes les apps en même temps, de sorte que votre 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 (Machine Learning) et WebAssembly sont deux des ajouts les plus récents. Par exemple, avec l’apprentissage automatique, vous pouvez écrire des applications qui recherchent des anomalies dans les données en continu. Avec WebAssembly, vous pouvez 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). Vous pouvez désormais é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 (NdT : sauf le bureau Linux, pour ça il y AvaloniaUI). .NET MAUI sera publié un peu plus tard que .NET 6. Nous avons consacré beaucoup de temps et d’efforts à .NET MAUI et nous sommes très enthousiastes à l’idée de le mettre à disposition et de voir les applications .NET MAUI en production.

Bien entendu, les applications .NET sont toujours à l’aise sur le bureau Windows – avec Windows Forms et WPF – et dans le cloud avec ASP.NET Core.
Ce sont les types d’applications que nous proposons depuis très longtemps et elles continuent d’être très populaires.
Nous les avons améliorées dans .NET 6.

Cibler .NET 6

Toujours dans l’optique d’une plate-forme étendue, il est facile d’écrire du code .NET sur tous ces systèmes d’exploitation.
Pour cibler .NET 6, vous devez utiliser un cadre cible .NET 6, comme le suivant :

    <TargetFramework>net6.0</TargetFramework>

L’identifiant net6.0 (Target Framework Moniker) vous donne accès à toutes les API multiplateformes offertes par .NET. C’est la meilleure option si vous écrivez des applications console, des applications Web ou des bibliothèques multiplateformes réutilisables.

Si vous ciblez un système d’exploitation spécifique (comme si vous écrivez une application Windows Forms ou iOS), il existe un autre ensemble de TFM (qui ciblent chacun un système d’exploitation évident) que vous pouvez utiliser. Ils vous donnent accès à toutes les API de net6.0, plus un certain nombre d’API spécifiques au système d’exploitation.

    net6.0-android
    net6.0-ios
    net6.0-maccatalyst
    net6.0-tvos
    net6.0-windows

Les TFM sans version équivalent chacun à cibler la version de système d’exploitation la plus basse prise en charge par .NET 6. Vous pouvez spécifier une version de système d’exploitation si vous voulez être spécifique ou avoir accès à des API plus récentes.
Les modules TFM net6.0 et net6.0-windows sont pris en charge (comme pour .NET 5). Les TFM Android et Apple sont nouveaux avec .NET 6 et sont actuellement en phase d’aperçu. Ils seront pris en charge lors d’une mise à jour ultérieure de .NET 6.

Il n’y a pas de relations de compatibilité entre les TFM spécifiques au système d’exploitation. Par exemple, net6.0-ios n’est pas compatible avec net6.0-tvos. Si vous souhaitez partager du code, vous devez le faire avec des sources avec des déclarations #if ou des binaires avec du code ciblé net6.0 (NdT : vous pouvez aussi utiliser l’attribut SupportedOSPlatform allié à la classe OperatingSystem, c’est détaillé plus loin).

Les nouveautés pour le développement Web

Voici un échantillon des nouvelles fonctionnalités et améliorations pour ASP.NET Core pour .NET 6 :

  • Rechargement à chaud (Hot Reload) : Appliquez les modifications apportées aux fichiers sources Razor, C# et CSS dans votre application en cours d’exécution pendant le développement sans avoir à recompiler et à redémarrer l’application ;
  • API minimales : Créez une nouvelle application ASP.NET Core avec seulement quelques lignes de code en utilisant les dernières fonctionnalités C# et un modèle d’hébergement simplifié ;
  • Streaming asynchrone : Diffusez des données de manière asynchrone depuis le serveur sans avoir besoin de mettre en mémoire tampon ;
  • IAsyncDisposable : Prise en charge de IAsyncDisposable sur les contrôleurs, les modèles de page et les composants de vue. Cela permet de libérer une ressource native (socket réseau, mémoire native…) sans bloquer le code appelant ;
  • Bootstrap 5.1 : ASP.NET Core embarque désormais Bootstrap 5.1 ;
  • Analyse des références nulls : L’analyse des références nulls en C# est désormais activée par défaut pour tous les patrons de conception (templates) pour les projets Web. Pour rappel, les Nullable Reference Types permet d’éviter les NullReferenceException avant d’exécuter le code. Les annotations ajoutées au code source de ASP .NET Core permettent désormais au compilateur de détecter davantage de cas et d’émettre un Warning ;
  • Isolation CSS pour les pages et les vues : Étendez les styles CSS à des pages ou des vues spécifiques à l’aide de fichiers .cshtml.css. Fini les conflits !
  • Modules JavaScript : Placez des modules JavaScript connexes à côté des pages, des vues et des composants à l’aide des fichiers .cshtml.js et .razor.js.

Améliorations concernant Blazor

Pour rappel, Blazor est un framework d’application Web permettant d’éviter entièrement JavaScript. Les applications Blazor reposent sur des composants, plutôt que sur le pattern Modèle-Vue-Contrôleur traditionnel. Ce modèle traditionnel est toujours présent et bien vivant pour les utilisateurs de ASP .NET Core MVC.

Il est toujours possible d’appeler JavasScript via l’interface IJSRuntime, ou d’avoir le code C# qui soit appelé par Javascript, si besoin.

Autres améliorations

Pour une liste complète de toutes les nouveautés d’ASP.NET Core dans .NET 6, consultez les notes de publication d’ASP.NET Core dans .NET 6.

Performance

Depuis le lancement du projet .NET Core, l’équipe s’intéresse de plus en plus aux performances (NdT: et met à disposition des outils tels que PerfCollect). Stephen Toub fait un travail remarquable pour rendre compte de l’évolution des performances de .NET à chaque version. Si vous n’en avez pas eu l’occasion, je vous recommande de jeter un coup d’œil à son article sur les améliorations des performances dans .NET 6 (NdT : lien vers la série complète).

En voici ce que j’ai retenu ci-dessous.

Optimisation dirigée par les profils dynamique

Dynamic Profile-guided Optimization (PGO) peut améliorer sensiblement et de manière stable les performances d’un programme. Par exemple, PGO donne une amélioration de 26 % (510 K -> 640 K) du nombre de requêtes traitées par seconde pour le benchmark TechEmpower JSON "MVC".

La PGO dynamique s’appuie sur la compilation par paliers (Tiered Compilation), qui permet aux méthodes d’être d’abord compilées très rapidement (niveau 0) afin d’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 avéré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, qui s’intègre à la compilation à la volée.

La PGO dynamique aura des temps de démarrage légèrement plus importants que le runtime par défaut, car il y a du code supplémentaire qui s’exécute dans les méthodes de niveau 0 pour observer le comportement des méthodes.

Pour activer cette fonctionnalité, définissez la variable d’environnement DOTNET_TieredPGO=1 dans l’environnement où votre application sera exécutée. Vous devez également vous assurer que Tiered Compilation est activé (par défaut). Dynamic PGO est opt-in parce qu’il s’agit d’une technologie nouvelle et importante. Nous souhaitons que l’utilisation de cette technologie soit soumise à une période de tests et que les commentaires qui en découlent permettent de s’assurer qu’elle est entièrement testée. Nous avons fait la même chose avec la compilation par paliers. La PGO dynamique est pris en charge et est déjà utilisé en production par au moins un très grand service Microsoft. Nous vous encourageons à l’essayer.

Vous pouvez en savoir plus sur les avantages de la PGO dynamique dans le billet de blog sur les Performance de .NET 6, y compris le microbenchmark suivant, qui mesure le coût d’un énumérateur LINQ particulier.

    private IEnumerator<long> _source = Enumerable.Range(0, long.MaxValue).GetEnumerator();

    [Benchmark]
    public void MoveNext() => _source.MoveNext();

Voici le résultat, avec et sans.

Méthode        Moyenne     Taille du code
PGO Absente     1.905 ns    30 octets
PGO Activée    0.7071 ns   105 octets

C’est une différence assez importante, mais la taille du code a également augmenté, ce qui pourrait surprendre certains lecteurs. Il s’agit de la taille du code assembleur généré par le JIT, et non des allocations mémoire (même si éviter les allocations mémoire est un type d’optimisation très utilisé). Vous trouverez une bonne explication à ce sujet dans le billet sur les performances de .NET 6.

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 chargements de code sans doute inutilisé.

Pour le contexte, la répartition des interfaces 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, la 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 à une interface virtuelle via IEnumerator. C’est une grande victoire si le code "chaud" est appelé la plupart du temps.

C’est ici que la magie opère. 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 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 source est ce Enumerable+RangeIterator : si ce n’est pas le cas, alors il saute à la section froide que nous avons 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 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 d’inliner cette méthode MoveNext. L’effet au final 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. C’est le genre de gains que nous voulions obtenir lorsque nous avons commencé à imaginer la PGO dynamique.

La PGO dynamique est évoquée de nouveau dans la section sur le compilateur juste à temps RyuJIT.

Améliorations des API d’E/S sur les 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 ! Nous avons é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), nous avons fait en sorte que les opérations asynchrones ne nécessitent aucune allocation ! De plus, nous avons uniformisé le comportement pour les cas limites où les implémentations Windows et Unix étaient différentes (lorsque cela était possible).

Les améliorations de performance de cette réécriture sont bénéfiques pour 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 banc d’essai suivant écrit 100 Mo dans un nouveau fichier.

    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, nous avons observé une accélération de quatre fois et une diminution de l’allocation de plus de 1 200 fois :

    Method              Runtime     Mean        Ratio   Allocated
    Write100MBAsync     .NET 5.0    1,308.2 ms  1.00    3,809 KB
    Write100MBAsync     .NET 6.0    306.8 ms    0.24    3 KB

Nous avons également identifié le besoin de fonctionnalités d’E/S sur les fichiers plus performantes  pour les cas d'usage suivants :

  • lectures et écritures simultanées ;
  • E/S de type "scatter/gather".

En conséquence, nous avons introduit de nouvelles API dans les classes System.IO.File et System.IO.RandomAccess pour ces cas.

    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)); // indice pour l’OS afin de préallouer l’espace disque
    await RandomAccess.WriteAsync(handle, buffers, fileOffset: 0); // sous Linux c’est un seul et unique appel système !
    }

L’échantillon ci-dessus démontre :

La fonction de pré-allocation de la taille améliore les performances puisque les opérations d’écriture n’ont pas besoin d’étendre le fichier et qu’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, celui-ci ayant déjà été réservé. L’API d’E/S Scatter/Gather réduit le nombre d’appels systèmes nécessaires pour écrire les données.

Vérification et casting d’interfaces plus rapides

Les performances du casting d’interface ont été améliorées de 16 % à 38 %. Cette amélioration est particulièrement utile pour le filtrage par motif du langage C# vers et entre les interfaces.

Pour rappel, un exemple de filtrage par motif est le nouvel usage du mot-clé switch apporté précédemment par C# 9:

public static LifeStage LifeStageAtAge(int age) => age switch
    {
        < 0 =>  LifeStage.Prenatal,
        < 2 =>  LifeStage.Infant,
        < 4 =>  LifeStage.Toddler,
        < 6 =>  LifeStage.EarlyChild,
        < 12 => LifeStage.MiddleChild,
        < 20 => LifeStage.Adolescent,
        < 40 => LifeStage.EarlyAdult,
        < 65 => LifeStage.MiddleAdult,
        _ =>    LifeStage.LateAdult,
    };

vérification d’interfaces plus rapide

Ce graphique illustre l’ampleur de l’amélioration via un banc d’essai représentatif.

L’un des principaux avantages du passage de certaines parties du moteur d’exécution de .NET de C++ à C# est qu’il réduit la barrière à l’entrée. Cela inclut le casting d’interface, qui a été déplacé vers C# lors d’un des premiers changements apportés lors de l’élaboration de .NET 6. Beaucoup de personnes dans l’écosystème .NET maîtrisent davantage le C# comparé au C++ (et le runtime utilise des modèles C++ difficiles à appréhender). 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 des contributeurs et la qualité de leurs contributions sous leurs différentes formes (code, documentation, tests…).

Le crédit de cette amélioration revient à Ben Adams.

Générateurs de code source pour System.Text.Json

Nous avons ajouté un générateur de code source pour System.Text.Json qui évite le besoin d’utiliser la réflexion et la génération de code au moment de l’exécution, et qui permet de générer un code de sérialisation optimal au moment de la construction. Les sérialiseurs sont généralement écrits avec des techniques très conservatrices parce qu’ils doivent l’être. Cependant, si vous lisez votre propre code source de sérialisation (qui utilise un sérialiseur), vous pouvez voir quels sont les choix évidents qui peuvent rendre un sérialiseur beaucoup plus optimal dans votre cas spécifique. C’est exactement ce que fait ce nouveau générateur de sources.

Outre l’amélioration des performances et la réduction de la mémoire, le générateur de sources produit un code optimal pour le découpage du code assembleur. Cela peut aider à produire des applications plus petites.

La sérialisation des POCO est un scénario très courant. En utilisant le nouveau générateur de sources, nous observons que la sérialisation est ~1.6x plus rapide avec notre banc d’essai.

Method                  Mean        StdDev      Ratio
Serializer              243.1 ns    9.54 ns     1.00
SrcGenSerializer        149.3 ns    1.91 ns     0.62

Le benchmark de mise en cache TechEmpower permet de tester la mise en cache en mémoire d’une plateforme ou d’un framework d’informations provenant d’une base de données. L’implémentation .NET du benchmark effectue la sérialisation JSON des données mises en cache afin de les envoyer comme réponse au harnais de test.

Variant                     Requests/sec    Requests
net5.0                      243,000         3,669,151
net6.0                      260,928         3,939,804
net6.0 + JSON source gen    364,224         5,499,468

Nous observons un gain de ~100 K requêtes par seconde (~40 % d’augmentation).
.NET 6 obtient un débit 50 % plus élevé que .NET 5 lorsqu’il est combiné avec les améliorations de performance de MemoryCache !

C# 10

L’un des principaux thèmes de C# 10 est la poursuite du processus de simplification qui a débuté avec les instructions de premier niveau de C# 9. Les nouvelles fonctionnalités suppriment encore plus de cérémonies de Program.cs, ce qui permet d’obtenir des programmes aussi courts qu’une seule ligne. Elles ont été inspirées par des discussions avec des personnes – étudiants, développeurs professionnels et autres – n’ayant aucune expérience préalable du C# et par l’apprentissage de ce qui fonctionne le mieux et est intuitif pour eux.

Ainsi, un Hello World en C# est désormais composé d’une seule ligne :

Console.WriteLine("Hello World!");

La plupart des patrons de conception du SDK .NET ont été mis à jour pour offrir une expérience beaucoup plus simple et plus concise. Ce qui est maintenant possible avec C# 10. Nous avons entendu des commentaires selon lesquels certaines personnes n’aiment pas les nouveaux modèles parce qu’ils ne sont pas destinés aux experts, qu’ils suppriment l’orientation objet, qu’ils suppriment des concepts qu’il est important d’apprendre dès le premier jour d’apprentissage du langage C# ou qu’ils encouragent l’écriture d’un programme entier dans un seul fichier. Objectivement, aucun de ces points n’est vrai. Le nouveau modèle est tout aussi destiné et tout aussi approprié aux étudiants qu’aux développeurs professionnels. Il est cependant différent du modèle dérivé du C que nous avons connu jusqu’à .NET 6.

Il y a d’autres fonctionnalités et améliorations apportées par C# 10, y compris les structures d’enregistrement.

Directives d’import globales

Les directives d’utilisation globale vous permettent de spécifier une directive d’utilisation une seule fois et de l’appliquer à chaque fichier que vous compilez.

Les exemples suivant montrent l’étendue de la syntaxe :

    global using System;
    global using static System.Console;
    global using Env = System.Environment;

Vous pouvez les ajouter dans n’importe quel fichier .cs, y compris Program.cs.

Les usings implicites quant à eux sont des concepts propres à MSBuild permettant d’ajouter automatiquement des directives globales à un projet, selon le SDK utilisé (console, ASP .NET…). Par exemple, les usings implicites disponibles pour une application console diffèrent de ceux disponibles pour une application Web.

Cette fonctionnalité n’est pas active par défaut pour les projets existants. Il faut la rajouter ainsi :

    <ImplicitUsings>enable</ImplicitUsings>

Mais ils font déjà partie des patrons de conception. Pour plus d’informations, consultez ce lien.

Espaces de noms au niveau fichier

Les espaces de noms à l’échelle du fichier vous permettent de déclarer l’espace de noms d’un fichier entier sans imbriquer le reste du contenu dans des { … }. Un seul espace de noms est autorisé, et il doit être placé avant la déclaration de tout type.

La nouvelle syntaxe tient en une seule ligne :

    namespace MyNamespace;
    class MyClass { ... } // Pas d'indentation

C’est une alternative à l’ancienne syntaxe :

    namespace MyNamespace
    {
        class MyClass { ... } // Tout est indenté
    }

Cela est intéressant pour le cas extrêmement courant où il n’y a de toutes façons qu’un seul espace de noms par fichier.

Structures d’enregistrement

C# 9 a introduit les enregistrements comme une forme spéciale de classes orientées valeur. En C# 10, vous pouvez également déclarer des enregistrements qui sont des structs. Les structures en C# ont déjà l’égalité de valeur, mais les records structs ajoutent un opérateur == et une implémentation de IEquatable, ainsi qu’une implémentation de ToString basée sur la valeur :

   public record struct Person
    {
        public string FirstName { get; init; }
        public string LastName { get; init; }
    }

Tout comme les classes d’enregistrement, les structures d’enregistrement peuvent être « positionnelles », ce qui signifie qu’elles ont un constructeur primaire qui déclare implicitement les membres publics correspondant aux paramètres :

    public record struct Person(string FirstName, string LastName);

Cependant, contrairement aux classes d’enregistrement, les membres publics implicites sont des propriétés mutables auto-implémentées. Ainsi, les structures d’enregistrement sont une évolution naturelle des tuples. Par exemple, si vous avez un type de retour qui est (string FirstName, string LastName) et que vous pouvez facilement déclarer la structure d'enregistrement positionnel correspondante et garder l'aspect mutable de la sémantique.

Si vous voulez un enregistrement immuable avec des propriétés en lecture seule, vous pouvez déclarer l’ensemble de la structure d’enregistrement en lecture seule (comme pour les autres structures) ainsi :

    public readonly record struct Person(string FirstName, string LastName) ;

C# 10 prend également en charge les expressions with, non seulement pour les structures d’enregistrement, mais aussi pour toutes les structures, ainsi que pour les types anonymes :

    var updatedPerson = person with { FirstName = "Mary" };

F# 6

F# 6 a pour but de rendre F# plus simple et plus performant. Cela s’applique à la conception du langage, à la bibliothèque et aux outils. Notre objectif avec F# 6 (et au-delà) était de supprimer les cas particuliers du langage qui surprennent les utilisateurs ou qui constituent des obstacles à l’apprentissage de F#. Nous sommes très heureux d’avoir travaillé avec la communauté F# dans cet effort continu.

Rendre F# plus rapide et interopérable

La syntaxe new task {...} crée directement une tâche et la démarre. C’est l’une des fonctionnalités les plus importantes de F# 6, qui rend les tâches asynchrones plus simples, plus performantes et plus interopérables avec C# et d’autres langages .NET. Auparavant, pour créer des tâches .NET, il fallait utiliser async {…} pour créer une tâche et invoquer Async.StartImmediateAsTask.

La fonctionnalité de task {...} est construite sur une fondation appelée « code pouvant être repris » (RFC FS-1087). Le code pouvant être repris est une fonctionnalité de base, et nous prévoyons de l’utiliser pour construire d’autres machines à états asynchrones et itératives à haute performance à l’avenir.

F# 6 ajoute également d’autres fonctionnalités de performance pour les auteurs de bibliothèques, notamment InlineIfLambda et des représentations non encadrées pour les modèles actifs F#. Une amélioration particulièrement significative des performances concerne la compilation des expressions de listes et de tableaux, qui sont désormais jusqu’à quatre fois plus rapides et dont le débogage est également amélioré et simplifié.

F# est plus facile à apprendre et plus uniforme

F# 6 permet d’utiliser la syntaxe d’indexation expr[idx]. Jusqu’à présent, F# utilisait expr.[idx] pour l’indexation. L’abandon de l’annotation du point est basé sur les commentaires répétés des nouveaux utilisateurs de F#, selon lesquels l’utilisation du point est perçue comme une divergence inutile par rapport à la pratique standard qu’ils attendent. Dans le nouveau code, nous recommandons l’utilisation systématique de la nouvelle syntaxe d’indexation expr[idx]. Nous devrions tous adopter cette syntaxe en tant que communauté.

La communauté F# a apporté des améliorations clés pour rendre le langage F# plus uniforme dans F# 6. La plus importante d’entre elles consiste à supprimer un certain nombre d’incohérences et de limitations dans les règles d’indentation de F#. Parmi les autres ajouts de conception visant à rendre F# plus uniforme, citons l’ajout de patterns as, permettant la création d’« opérations personnalisées surchargées » dans les expressions de calcul (utiles pour les DSL).

Cela permet aussi l’usage de '_' pour signifier les éléments ignorés sur les liaisons d’utilisation et permet l’usage de %B pour le formatage binaire en sortie. La bibliothèque standard de F# ajoute de nouvelles fonctions pour la copie et la mise à jour de listes, de tableaux et de séquences, ainsi que des fonctions intrinsèques NativePtr supplémentaires. Certaines fonctions héritées de F#, dépréciées depuis la version 2.0, entraînent désormais des erreurs. La plupart de ces changements mettent en conformité F# avec les usages habituels, ce qui diminue les surprises lors de l’apprentissage du langage.

F# 6 a également ajouté la prise en charge de conversions « implicites » et « dirigées par le type » supplémentaires dans F#. Cela signifie moins de changements de types (upcasts) explicites, et ajoute un support de première classe pour les conversions implicites. F# est également ajusté pour être mieux adapté à l’ère des bibliothèques numériques utilisant des entiers 64 bits, avec un élargissement implicite pour les entiers 32 bits vers des entiers 64 bits.

Amélioration de l’outillage F#

Les améliorations de l’outillage dans F# 6 facilitent le développement au quotidien. Le nouveau « débogage de pipeline » vous permet d’avancer, de définir des points d’arrêt et d’inspecter les valeurs intermédiaires pour la syntaxe de piping F# input |> f1 |> f2. L’affichage de débogage des valeurs implicites a été amélioré, éliminant ainsi une source de confusion courante lors du débogage. L’outillage F# est désormais plus performant, le compilateur F# effectuant l’étape d’analyse syntaxique en parallèle. Les outils de l’IDE F# ont également été améliorés. Enfin, le scripting en F# est maintenant encore plus robuste, vous permettant d’épingler la version du SDK .NET utilisé par le biais de fichiers global.json.

Rechargement à chaud

Le rechargement à chaud est fonctionnalité axée sur la productivité des développeurs. Elle vous permet d’apporter une grande variété de modifications au code d’une application en cours d’exécution, réduisant ainsi le temps que vous devez passer à attendre que les applications se reconstruisent, redémarrent ou reviennent au même endroit où vous étiez après avoir apporté une modification au code.

Le rechargement à chaud est disponible à la fois via l’outil dotnet watch et Visual Studio 2022. Vous pouvez utiliser Hot Reload avec une grande variété de types d’applications telles que ASP.NET Core, Blazor, .NET MAUI, Console, Windows Forms (WinForms), WPF, WinUI 3, Azure Functions, et autres.

Lorsque vous utilisez la ligne de commande, il vous suffit de lancer votre application .NET 6 à l’aide de dotnet watch, d’effectuer toute modification prise en charge et, lors de l’enregistrement du fichier (par exemple dans Visual Studio Code), ces modifications seront immédiatement appliquées. Si les modifications ne sont pas prises en charge, les détails seront enregistrés dans le terminal.
ligne de commande hot reload
Cette image montre une application MVC lancée avec dotnet watch. J’ai apporté des modifications aux fichiers .cs et .cshtml (comme indiqué dans le journal) et les deux ont été appliquées au code et reflétées dans le navigateur très rapidement, en moins d’une demi-seconde.

Lorsque vous utilisez Visual Studio 2022, il vous suffit de lancer votre application, d’effectuer une modification prise en charge et d’utiliser le nouveau bouton « Hot Reload » (affiché dans l’image suivante) pour appliquer ces modifications. Vous pouvez également choisir d’appliquer les changements lors de la sauvegarde grâce au menu déroulant du même bouton. Lorsque vous utilisez Visual Studio 2022, le rechargement à chaud est disponible pour plusieurs versions de .NET, pour .NET 5+, .NET Core et .NET Framework. Par exemple, vous pourrez apporter des modifications au code-behind d’un gestionnaire d’évènement OnClickEvent pour un bouton.
Le rechargement a encore quelques cas non-pris en charge, comme le point d’entrée d’une application (la méthode Main).
Hot Reload Visual Studio 2022 experience
Note : Il existe un bogue dans RuntimeInformation.FrameworkDescription montré dans cette image qui sera corrigé très bientôt.

Le rechargement à chaud fonctionne aussi avec la fonctionnalité existante Modifier & Continuer et le rechargement à chaud pour le code XAML qui permet de modifier les interfaces graphiques en temps réel. Quant aux langages, cela fonctionne actuellement avec C# et VB .NET (mais pas F#).

Sécurité

La sécurité a été considérablement améliorée dans .NET 6. C’est toujours un focus important pour l’équipe, et cela comprend la modélisation des menaces, la cryptographie et les mesures de défense en profondeur.

Sous Linux, nous nous appuyons sur OpenSSL pour toutes les opérations cryptographiques, y compris pour TLS (requis pour HTTPS). Sous macOS et Windows, nous nous appuyons sur les fonctionnalités fournies par le système d’exploitation couvrant le même besoin. Avec chaque nouvelle version de .NET, nous devons souvent ajouter la prise en charge d’une nouvelle version d’OpenSSL. .NET 6 ajoute la prise en charge d'OpenSSL 3.

Les plus grands changements d’OpenSSL 3 sont un module FIPS 140-2 amélioré et une licence d’utilisation plus simple.

.NET 6 exige 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, vous commencerez probablement à utiliser OpenSSL 3 lorsque la distribution Linux que vous utilisez l’adoptera par défaut. La plupart des distributions ne l’ont pas encore fait. Par exemple, si vous installez .NET 6 sur Red Hat Enterprise Linux 8 ou Ubuntu 20.04, vous ne commencerez pas (au moment de la rédaction de cet article) à utiliser OpenSSL 3.

OpenSSL 3, Windows 10 21H1 et Windows Server 2022 prennent tous en charge ChaCha20Poly1305. Vous pouvez utiliser cette nouvelle méthode de chiffrement authentifié avec .NET 6 (si votre environnement le prend en charge).

Merci à Kevin Jones pour le support Linux de ChaCha20Poly1305.

Nous avons également publié une nouvelle feuille de route sur les mesures de sécurité des runtime. Il est important que le moteur d’exécution que vous utilisez soit à l’abri des attaques les plus usuelles. Nous répondons à ce besoin. Dans .NET 6, nous avons construit les premières implémentations de W ^ X et de la technologie Intel Control-flow enforcement (CET). W ^ X est entièrement pris en charge, activé par défaut pour macOS Arm64, et est optionnel pour les autres environnements. CET est en option et à l'état d'aperçu pour tous les environnements. Nous prévoyons que les deux technologies seront activées par défaut pour tous les environnements dans .NET 7, c’est-à-dire dès novembre 2022.

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 de l'industrie informatique. 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 concordent. Ces partenariats étroits nous ont beaucoup aidés.

  • Nous remercions tout particulièrement Apple, qui a envoyé à notre équipe un grand nombre de kits de développement Arm64 sur lesquels travailler avant le lancement de la puce M1, et qui nous a apporté un soutien technique important ;
  • Nous remercions tout particulièrement Arm Holdings, dont les ingénieurs ont revu le code de nos modifications pour Arm64 et ont également apporté des améliorations en termes de performances.

Nous avons ajouté le support initial pour Arm64 avec .NET Core 3.0 et Arm32 auparavant. L’équipe a réalisé des investissements importants pour Arm64 dans chacune des dernières versions, et cela va continuer dans un avenir proche. Dans .NET 6, nous nous sommes principalement concentrés sur la prise en charge des nouvelles puces Apple Silicon et du cas d’usage de l’émulation x64 sur les systèmes d’exploitation macOS et Windows Arm64.

Vous pouvez installer les versions Arm64 et x64 de .NET sur les systèmes d’exploitation macOS 11+ et Windows 11+ Arm64. Nous avons dû faire plusieurs choix de conception et modifier notre logiciel pour que cela fonctionne.

Notre stratégie est de toujours privilégier l’architecture native. Nous vous recommandons de toujours utiliser le SDK qui correspond à l’architecture native, c’est-à-dire le SDK Arm64 sur macOS et Windows Arm64. Le SDK est un vaste ensemble de logiciels. Il sera beaucoup plus performant en fonctionnement natif sur une puce Arm64 qu’en émulation. Nous avons mis à jour l’invite de commandes dotnet pour rendre cela plus facile. Nous n’allons jamais nous concentrer sur l’optimisation de l’émulation x64.

Par défaut, si vous exécutez une application .NET 6 avec le SDK Arm64, elle s’exécutera en Arm64. Vous pouvez facilement passer à l’exécution en x64 avec l’argument -a, en tapant par exemple dotnet run -a x64. Le même argument fonctionne pour les autres verbes de l’invite de commandes. Consultez l’article à propos de .NET 6 RC2 pour macOS et Windows Arm64 pour plus d’informations.

Il y a là une subtilité qui doit être décrite. Lorsque vous utilisez l’argument en ligne de commande -a x64, le SDK s’exécute toujours de manière native en Arm64. Il existe des points prédéterminés dans l’architecture du SDK .NET où des limites sont établies sur les processus. La plupart du temps, un processus doit être entièrement Arm64 ou entièrement x64. Je simplifie un peu, mais l’invite de commandes .NET s'attend à ce que la dernière création de processus faite par le SDK et lancé par ce dernier soit créé avec l’architecture demandée, comme, par exemple, "x64". C’est dans ce dernier processus que votre code s'exécute. De cette façon, vous bénéficiez des avantages de l’architecture Arm64 en tant que développeur, mais votre code s’exécute avec l’architecture sélectionnée. Ceci n’est pertinent que si vous avez besoin d’exécuter du code en x64. Si ce n’est pas le cas, vous pouvez tout simplement tout exécuter en Arm64 tout le temps, et tout va pour le mieux.

Prise en charge de Arm64

Voici les points essentiels que vous devez connaître, pour macOS et Windows Arm64 :

  • les SDK .NET 6 Arm64 et x64 sont pris en charge et recommandés ;
  • tous les runtimes Arm64 et x64 pris en charge le sont ;
  • les SDK .NET Core 3.1 et .NET 5 fonctionnent mais offrent moins de possibilités et, dans certains cas, ne sont pas entièrement pris en charge ;
  • l'outil en ligne de commande dotnet test ne fonctionne pas encore correctement avec l’émulation x64. Nous travaillons sur ce point. dotnet test sera amélioré dans le cadre de la version 6.0.200, et peut-être même avant.

Consultez la section Support de .NET pour macOS et Windows Arm64 pour des informations plus complètes.

Linux est absent de cette discussion. Il ne prend pas en charge l’émulation x64 de la même manière que macOS et Windows. Par conséquent, ces nouvelles fonctionnalités en ligne de commande et l’approche de prise en charge ne s’appliquent pas directement à Linux, et Linux n’en a pas besoin.

Windows Arm64

Nous disposons d’un outil simple qui montre l’environnement sur lequel tourne .NET appelé dotnet-runtimeinfo.

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

Comme vous pouvez le voir, l’outil fonctionne nativement sur Windows Arm64. Voici à quoi cela ressemble avec ASP.NET Core :

windows-arm64

macOS Arm64

L’expérience est similaire en tous points sur macOS arm64 :

rich@MacBook-Air app % dotnet --version
6.0.100
rich@MacBook-Air app % dotnet --info | grep RID
 RID:         osx-arm64
rich@MacBook-Air app % cat Program.cs 
using System.Runtime.InteropServices;
using static System.Console;

WriteLine($"Hello, {RuntimeInformation.OSArchitecture} from {RuntimeInformation.FrameworkDescription}!");
rich@MacBook-Air app % dotnet run
Hello, Arm64 from .NET 6.0.0-rtm.21522.10!
rich@MacBook-Air app % dotnet run -a x64
Hello, X64 from .NET 6.0.0-rtm.21522.10!

Cette image montre que l’exécution en mode natif Arm64 est la valeur par défaut du SDK Arm64 et qu’il est facile de passer de l’exécution sur Arm64 à l’exécution en mode x64 en utilisant l’argument -a. L’expérience est aussi reproductible sur Windows Arm64.

macos arm64

Cette image montre la même chose, mais avec ASP.NET Core. Le même SDK .NET 6 Arm64 est utilisé que dans l’image précédente.

Docker sur Arm64

Docker prend en charge les conteneurs fonctionnant avec une architecture native et en émulation, l’architecture native étant la valeur par défaut. Cela semble évident mais peut être déroutant lorsque la majorité du catalogue du Docker Hub est orienté x64. Vous pouvez utiliser --platform linux/amd64 pour demander une image x64.

Nous ne prenons en charge l’exécution des images de conteneurs Linux Arm64 .NET que sur les systèmes d’exploitation Arm64. En effet, nous n’avons jamais pris en charge l’exécution de .NET dans QEMU, qui est utilisé par Docker pour l’émulation d'architecture. Il semble que cela soit dû à une limitation de QEMU.
docker arm64
Cette image illustre l’exemple de programme console que nous maintenons. C’est un exemple amusant, car il contient une logique de base pour l’impression d’informations sur les limites du CPU et de la mémoire avec lesquelles vous pouvez jouer. Dans l’image, j’ai défini moi-même les limites du CPU et de la mémoire.

Essayez à votre tour :

docker run --rm mcr.microsoft.com/dotnet/samples

Performance Arm64

Les projets de prise en charge de l’émulation Apple Silicon et x64 étaient très importants pour nous, mais nous avons également amélioré les performances sur Arm64 en général.
arm64 perfs
Cette image montre une amélioration de la mise à zéro du contenu de la pile des appels, 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 c’est bas, mieux c’est.

Conteneurs

.NET 6 est mieux taillé pour les conteneurs, principalement sur la base de toutes les améliorations discutées dans cet article, à la fois pour Arm64 et x64. Nous avons également apporté des changements clés qui aideront à résoudre davantage de cas d’usage. Ce lien montre certaines de ces améliorations testées ensemble.

Les améliorations apportées aux conteneurs Windows et la nouvelle variable d’environnement ont également été incluses dans la mise à jour de novembre du conteneur .NET Framework 4.8, qui sortira le 9 novembre 2021.

Les notes de mise à jour sont disponibles sur nos dépôts docker :

Conteneurs Windows

.NET 6 ajoute la prise en charge des conteneurs Windows à processus isolé. Si vous utilisez des conteneurs Windows dans Azure Kubernetes Service (AKS), vous vous appuyez sur des conteneurs à 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 conteneurs Hyper-V.

La valeur principale de ce changement est que Environment.ProcessorCount rapportera maintenant la valeur correcte avec les conteneurs Windows isolés des processus. Si vous créez un conteneur à 2 cœurs 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 l’invite de commandes de Docker, Kubernetes ou tout autre orchestrateur/exécutant de conteneurs. Cette valeur est utilisée par diverses parties de .NET à des fins de mise à l’échelle, notamment le ramasse-miettes de .NET (bien qu’il s’appuie sur une API connexe plus bas niveau). Les bibliothèques communautaires s’appuient également sur cette API pour la mise à l’échelle.

Nous avons récemment validé cette nouvelle capacité avec un client, sur des conteneurs Windows en production sur AKS en utilisant un grand ensemble de pods Azure. Ils ont pu fonctionner avec succès avec 50 % de mémoire (par rapport à leur configuration typique), un niveau qui entraînait auparavant des exceptions OutOfMemoryException et StackOverflowException. Ils n’ont pas pris le temps de trouver la configuration de mémoire minimale, mais nous avons deviné qu’elle était nettement inférieure à 50 % de leur configuration de mémoire typique. À la suite de ce changement, ils vont passer à des configurations Azure moins chères, ce qui leur permettra de faire des économies. Il s’agit là d’un gain facile et appréciable, simplement en effectuant une mise à niveau.

Optimisation du passage à l’échelle

Des utilisateurs nous ont dit que certaines applications ne peuvent pas atteindre une mise à l’échelle optimale lorsque Environment.ProcessorCount indique la valeur correcte. Si cela ressemble à l’opposé de ce que vous venez de lire pour les conteneurs Windows, c’est un peu le cas. .NET 6 propose désormais la variable d’environnement DOTNET_PROCESSOR_COUNT pour contrôler manuellement la valeur de Environment.ProcessorCount. Dans un cas d’utilisation typique, une application peut être configurée avec 4 cœurs sur une machine de 64 cœurs, et évoluer au mieux en termes de 8 ou 16 cœurs. Cette variable d’environnement peut être utilisée pour activer cette mise à l’échelle.

Ce modèle peut sembler étrange, car les valeurs de Environment.ProcessorCount et --cpus (via l’invite de commandes de Docker) peuvent différer. Les moteurs d’exécution des conteneurs, par défaut, sont orientés en termes d’équivalents de cœurs, et non de cœurs réels. Cela signifie que lorsque vous dites que vous voulez 4 cœurs, vous obtenez l’équivalent du temps CPU de 4 cœurs, mais votre application peut (en théorie) fonctionner sur beaucoup plus de cœurs, même sur les 64 cœurs d’une machine à 64 cœurs pendant une courte période. Cela pourrait permettre à votre application de mieux évoluer sur plus de 4 fils d’exécution (en continuant avec l’exemple), et allouer plus de fils d’exécution pourrait être bénéfique. Cela suppose que l’allocation des fils d’exécution est basée sur la valeur de Environment.ProcessorCount. Si vous choisissez de définir une valeur plus élevée, il est probable que votre application utilisera plus de mémoire. Pour certaines charges de travail, il s’agit d’un compromis facile. Il s’agit au moins d’une nouvelle option que vous pouvez tester.

Cette nouvelle fonctionnalité est prise en charge par les conteneurs Linux et Windows.

Docker propose également une fonction de groupes de CPU, qui permet d’affecter votre application à des cœurs spécifiques. Cette fonctionnalité n’est pas recommandée dans ce scénario, car alors le nombre de cœurs auxquels une application a accès est défini concrètement. Nous avons également constaté des problèmes lors de son utilisation avec les conteneurs Hyper-V, et elle n’est pas vraiment destinée à ce mode d’isolation.

De l’importance de Debian

Nous suivons de très près le cycle de vie et les plans de publication des distributions Linux et essayons de faire les meilleurs choix pour vous. Debian est la distribution Linux que nous utilisons pour nos images Linux par défaut. Si vous téléchargez l'un de nos conteneurs étiquetés en version 6.0 depuis l'un de nos dépôts, vous téléchargez une image Debian (en supposant que vous utilisez des conteneurs Linux). À chaque nouvelle version de .NET, nous nous demandons si nous devons adopter une nouvelle version de Debian.

Par principe, nous ne changeons pas la version de Debian pour nos étiquettes git habituelles, comme "6.0", au milieu de la phase de publication (NdT : .NET 6 a eu droit à deux Release Candidates). Si nous le faisions, certaines applications seraient certainement cassées. Cela signifie que le choix de la version de Debian au début de la publication est très important. De plus, ces images sont très utilisées, principalement parce qu’elles sont référencées par les « bonnes étiquettes ».

Les versions Debian et .NET ne sont naturellement pas planifiées ensemble. Lorsque nous avons commencé .NET 6, nous avons vu que la version bullseye de Debian serait probablement publiée en 2021. Nous avons décidé de faire un pari sur bullseye dès le début de la publication. Nous avons commencé à publier des images de conteneurs basées sur bullseye avec .NET 6 Preview 1 et avons décidé de ne pas regarder en arrière. Le pari était que la version finale de .NET 6 perdrait la course avec la version finale de bullseye. Le 8 août, nous ne savions toujours pas quand bullseye serait livré, ce qui laissait trois mois avant la sortie de notre propre version, le 8 novembre. Nous ne voulions pas livrer une version de production de .NET 6 sur une version préliminaire de Debian, mais nous sommes restés fermes sur le fait que nous allions perdre cette course.

Nous avons été agréablement surpris lorsque Debian 11 "bullseye" a été publiée le 14 août. Nous avons perdu la course mais gagné le pari. Cela signifie que les utilisateurs de .NET 6 obtiennent la meilleure et la plus récente Debian, par défaut, dès le premier jour. Nous pensons que Debian 11 et .NET 6 seront une excellente combinaison pour de nombreux utilisateurs. Désolé Buster, nous avons fait mouche.

Les nouvelles versions de la distribution incluent des versions majeures plus récentes de divers paquets dans leur flux de paquets et obtiennent souvent les corrections CVE plus rapidement. Cela s’ajoute à un noyau plus récent. Les utilisateurs sont mieux servis par une nouvelle version de distro.

En regardant un peu plus loin, nous allons commencer à planifier la prise en charge d'Ubuntu 22.04 d’ici peu. Ubuntu est une autre distro de la famille Debian et est populaire auprès des développeurs .NET. Nous espérons pouvoir offrir un support le jour même pour la nouvelle version Ubuntu LTS.

Chapeau à Tianon Gravi qui maintient les images Debian pour la communauté et nous aide lorsque nous avons des questions.

Dotnet monitor

dotnet monitor est un outil de diagnostic important pour les conteneurs. Il est disponible en tant qu’image de conteneur depuis un certain temps, mais dans un statut « expérimental » non pris en charge. Dans le cadre de .NET 6, nous publions une image dotnet monitor basée sur .NET 6 et entièrement prise en charge en production.

dotnet monitor est déjà utilisé par Azure App Service en tant que détail de mise en œuvre de leur expérience de diagnostic ASP.NET Core Linux. C’était l’un des scénarios envisagés, qui consiste à s’appuyer sur dotnet monitor pour fournir des expériences de plus haut niveau et de plus grande valeur.

Vous pouvez télécharger l’image dès maintenant :

docker pull mcr.microsoft.com/dotnet/monitor:6.0

dotnet monitor facilite l’accès aux informations de diagnostic – journaux, traces, vidages de processus – d’un processus .NET. Il est facile d’accéder à toutes les informations de diagnostic que vous souhaitez sur votre ordinateur de bureau, mais ces mêmes techniques familières peuvent ne pas fonctionner en production en utilisant des conteneurs, par exemple. dotnet monitor fournit un moyen unifié de collecter ces artefacts de diagnostic, qu’ils soient exécutés sur votre ordinateur de bureau ou dans un cluster Kubernetes. Il existe deux mécanismes différents pour la collecte de ces artefacts de diagnostic :

  • Une API HTTP pour la collecte ad-hoc d’artefacts. Vous pouvez appeler ces points de terminaison de l’API lorsque vous savez déjà que votre application rencontre un problème et que vous souhaitez recueillir davantage d’informations ;
  • Des déclencheurs pour une configuration basée sur des règles pour une collecte permanente d’artefacts. Vous pouvez configurer des règles pour collecter des données de diagnostic lorsqu’une condition souhaitée est remplie. Par exemple, collecter un vidage de processus lorsque l’usage du CPU reste élevé.

Le moniteur dotnet fournit une API de diagnostic commune pour les applications .NET qui fonctionne partout où vous le souhaitez avec tous les outils que vous voulez. L’« API commune » n’est pas une API .NET mais une API Web que vous pouvez appeler et interroger. dotnet monitor comprend un serveur Web ASP.NET qui interagit directement avec les données d’un serveur de diagnostic dans le runtime .NET et les expose. La conception de dotnet monitor permet une surveillance de haute performance en production et une utilisation sécurisée pour contrôler l’accès aux informations privilégiées. dotnet monitor interagit avec le runtime – au-delà des limites du conteneur – via un socket de domaine unix non adressable par Internet. Ce modèle de communication est parfaitement adapté à ce cas d’utilisation.

Journaux JSON structurés

À l’instar de la bibliothèque libre Serilog, nous avons adopté l’usage de journaux JSON structurés.

En effet, le formateur JSON est désormais le logger de la console par défaut dans l'image docker ASP .NET pour .NET 6. Dans .NET 5, la configuration par défaut était le formateur de console simple. Ce changement a été effectué afin d’avoir une configuration par défaut qui fonctionne avec des outils automatisés qui s’appuient sur un format lisible par une machine comme le JSON.

Désormais la sortie ressemble à ce qui suit pour l’image ASP .NET :

$ docker run --rm -it -p 8000:80 mcr.microsoft.com/dotnet/samples:aspnetapp
{"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory u0027{path}u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}}
{"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","KeyId":"86cafacf-ab57-434a-b09c-66a929ae4fd7","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrlu002BC to shut down.","State":{"Message":"Application started. Press Ctrlu002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrlu002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: /app","State":{"Message":"Content root path: /app","contentRoot":"/app","{OriginalFormat}":"Content root path: {contentRoot}"}}

Le type de format du journal peut être modifié en définissant ou en désactivant la variable d’environnement Logging_Console_FormatterName ou en modifiant le code (consultez Formatage du journal de la console pour plus de détails).

Après l’avoir modifié, vous obtiendrez une sortie comme celle qui suit (comme dans .NET 5) :

$ docker run --rm -it -p 8000:80 -e Logging__Console__FormatterName="" mcr.microsoft.com/dotnet/samples:aspnetapp
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {8d4ddd1d-ccfc-4898-9fe1-3e7403bf23a0} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app

Remarque : ce changement n’affecte pas le SDK .NET sur votre machine de développement, comme ce serait le cas avec dotnet run. Cette modification est spécifique à l’image du conteneur ASP .NET.

Prise en charge des mesures OpenTelemetry

Nous avons ajouté la prise en charge d’OpenTelemetry dans les deux dernières versions de .NET, dans le cadre de nos efforts en matière de télémétrie. Dans .NET 6, nous ajoutons la prise en charge de l’interface de programmation OpenTelemetry Metrics. En ajoutant le support pour OpenTelemetry, vos applications peuvent interagir de manière transparente avec d’autres systèmes OpenTelemetry.

System.Diagnostics.Metrics est l’implémentation .NET de la spécification de l’API OpenTelemetry Metrics. Les API Metrics sont conçues explicitement pour traiter les mesures brutes, dans le but de produire des résumés continus de ces mesures, de manière efficace et simultanée.

Les API comprennent la classe Meter qui peut être utilisée pour créer des "instruments" de mesure. Les API comprennent quatre classes d’instruments : Counter, Histogram, ObservableCounter et ObservableGauge pour prendre en charge différents scénarios de mesure. Les API mettent à disposition également la classe MeterListener qui permet d’écouter les mesures enregistrées par l’instrument à des fins d’agrégation et de regroupement.

L’implémentation OpenTelemetry de .NET sera, à terme, étendue pour utiliser ces nouvelles API.

Exemple d’enregistrement d’une mesure

Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");
Counter<int> counter = meter.CreateCounter<int>("Requests");
counter.Add(1);
counter.Add(1, KeyValuePair.Create<string, object>("request", "read"));

Exemple d’écoute

MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meterListener) =>
{
    if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb")
    {
        meterListener.EnableMeasurementEvents(instrument, null);
    }
};
listener.SetMeasurementEventCallback<int>((instrument, measurement, tags, state) =>
{
    Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.Start();

Windows Forms

Nous avons continué à apporter des améliorations clés à Windows Forms. .NET 6 comprend une meilleure accessibilité des contrôles Win32, la possibilité de définir une police par défaut pour l’ensemble de l’application, des mises à jour aux patrons de conception, etc.

Amélioration de l’accessibilité

Afin d’améliorer l'accessibilité, nous avons ajouté des fournisseurs UI Automation pour CheckedListBox, LinkLabel, Panel, ScrollBar, TabControl et TrackBar qui permettent à des outils comme le Narrateur et l’automatisation des tests d’interagir avec les éléments d’une application.

Police de caractères par défaut

Vous pouvez maintenant définir une police de caractère par défaut pour votre application via la méthode statique Application.SetDefaultFont.

    void Application.SetDefaultFont(Font font)

Applications minimalistes

Ce qui suit est une application Windows Forms minimale en .NET 6:

class Program
{
    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();
        Application.Run(new Form1());
    }
}

À l’occasion de cette nouvelle version, nous avons mis à jour la plupart des modèles pour qu’ils soient plus modernes et minimaux, y compris pour Windows Forms. Nous avons décidé de conserver le modèle Windows Forms un peu plus traditionnel, notamment en raison de la nécessité d’appliquer l’attribut [STAThread] au point d’entrée de l’application. Cependant, il y a plus en jeu qu’il n’y paraît.

(NdT: STAThread indique au runtime l'usage d'un modèle d'isolation des fils d'exécution, modèle offert par Windows)

En effet, ApplicationConfiguration.Initialize() est une interface de programmation générant le code source pour les appels suivants :

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetDefaultFont(new Font(...));
Application.SetHighDpiMode(HighDpiMode.SystemAware);

Les paramètres de ces appels sont configurables via les propriétés MSBuild dans les fichiers .csproj ou props.

Le concepteur Windows Forms dans Visual Studio 2022 est également conscient de ces propriétés (auparavant, il n'utilisait que la police par défaut), et peut vous montrer votre application telle qu’elle se présenterait au moment de l’exécution :

bootstrap-winforms

Mise à jour des patrons de conception

Les patrons de conception pour les applications Windows Forms utilisant le langage C# ont été mis à jour pour prendre en charge le nouvel amorceur d’application, les directives d’utilisation globales, les espaces de noms à l’échelle du fichier et les types de référence nullables.

Davantage de concepteurs de vues

Suite à la création des nouveaux concepteurs de vues pour Windows Forms et WPF, vous pouvez désormais créer un concepteur polyvalent (par exemple, un concepteur de rapports), car .NET 6 possède toutes les pièces manquantes pour les concepteurs et l’infrastructure liée aux concepteurs. Pour plus d’informations, consultez cet article de blog.

Applications autonomes

Dans .NET 6, les applications à fichier unique en mémoire ont été activées pour Windows et macOS. Dans .NET 5, ce type de déploiement était limité à Linux. Vous pouvez désormais publier un binaire à fichier unique qui est à la fois déployé et lancé comme un seul fichier, pour tous les systèmes d’exploitation pris en charge. Les applications à fichier unique n’extraient plus la bibliothèque standard vers des répertoires temporaires comme c’était le cas avec .NET Core 3.1, qui a introduit les applications autonomes.

Cette amélioration significative est basée sur un bloc de construction appelé "superhost". En .NET, L’"apphost" est l’exécutable qui lance votre application dans le cas d’une application normale, comme myapp.exe ou ./myapp. L’apphost contient le code permettant de trouver le runtime, de le charger et de lancer votre application avec ce runtime. Superhost quant à lui effectue toujours certaines de ces tâches mais utilise une copie liée statiquement de tous les binaires natifs de CoreCLR. Les applications autonomes de .NET 6 reposent désormais sur la liaison statique et non pas sur l’extraction d’une archive de la bibliothèque standard et du runtime.

Les dépendances natives (comme celles fournies avec un paquet NuGet) constituent l’exception notable à l’intégration d’un fichier unique. Elles ne sont pas incluses dans le fichier unique par défaut. Par exemple, les dépendances natives de WPF ne font pas partie du superhost, ce qui entraîne la création de fichiers supplémentaires à côté de l’application à fichier unique. Vous pouvez utiliser le paramètre IncludeNativeLibrariesForSelfExtract pour intégrer et extraire les dépendances natives.

Analyse statique

Nous avons amélioré l'analyse statique des applications à fichier unique pour permettre des avertissements personnalisés. Si vous disposez d’une API qui ne fonctionne pas dans le cadre d’une publication sur fichier unique, vous pouvez désormais la marquer avec l’attribut [RequiresAssemblyFiles], et un avertissement apparaîtra si l’analyseur est activé. L’ajout de cet attribut fera également taire tous les avertissements liés au fichier unique dans la méthode, de sorte que vous pouvez utiliser l’avertissement pour propager les avertissements vers le haut de votre interface publique.

L’analyseur de fichier unique est automatiquement activé pour les projets exe lorsque PublishSingleFile est défini sur true, mais vous pouvez également l’activer pour tout projet en définissant EnableSingleFileAnalysis sur true. Ceci est utile pour les auteurs de bibliothèques qui veulent prendre en charge le cas des applications à fichier unique.

Dans .NET 5, nous avions ajouté un avertissement au compilateur pour Assembly.Location et quelques autres interfaces de programmation qui se comportent différemment dans le contexte d'exécution des applications autonomes.

Compression

Les applications à fichier unique prennent désormais en charge la compression, qui peut être activée en définissant la propriété EnableCompressionInSingleFile à True. Au moment de l’exécution, les fichiers sont décompressés en mémoire si nécessaire. La compression peut permettre de réaliser d’énormes économies d’espace dans certains scénarios.

Examinons la publication de fichiers uniques, avec et sans compression, sur l’application NuGet Package Explorer.

Sans compression : 172 Mio

172 Mo

Avec compression : 71.6 Mio

71.6 Mo

Actuellement, la compression peut augmenter considérablement le temps de démarrage de l’application, notamment sur les plates-formes Unix. En effet le démarrage d’une application compressée sous Unix exige d’abord de la copier sur l’espace de stockage plutôt qu’en mémoire vive. Vous devez tester votre application après avoir activé la compression pour voir si le coût de démarrage supplémentaire est acceptable.

Déboguage d'applications à fichier unique

Les applications à fichier unique ne peuvent actuellement être déboguées qu’à l’aide de débogueurs natifs, comme WinDBG. Nous envisageons d’ajouter le débogage Visual Studio dans une version ultérieure de Visual Studio 2022.

Signature des applications autonomes sur macOS

Les applications à fichier unique répondent désormais aux exigences d’Apple en matière de notarisation et de signature sur macOS. Les changements spécifiques concernent la manière dont nous construisons les applications à fichier unique en termes de disposition discrète des fichiers.

Apple a commencé à appliquer de nouvelles exigences en matière de signature et de notarisation avec macOS Catalina. Nous avons travaillé en étroite collaboration avec Apple pour comprendre ces exigences et trouver des solutions qui permettent à une plateforme de développement comme .NET de fonctionner correctement dans cet environnement. Nous avons apporté des modifications et documenté les flux de travail des utilisateurs afin de satisfaire aux exigences d’Apple dans chacune des dernières versions de .NET. L’une des lacunes restantes était la signature d’applications autonomes, qui est une exigence désormais satisfaite pour distribuer une application .NET sur macOS, y compris dans la boutique macOS.

Élagage du langage intermédiaire

L’équipe travaille sur l’élagage de l’IL depuis plusieurs versions. .NET 6 représente une avancée majeure dans ce domaine. Nous nous sommes efforcés de produire un mode d’élagage plus agressif sûr et prévisible et avons donc décidé d’en faire le mode par défaut. TrimMode=link, qui était auparavant une option à activer, est désormais la valeur par défaut.

Nous avons adopté une stratégie à trois volets pour l’élagage revu et corrigé :

  • Améliorer la capacité d’élagage de la plate-forme .NET ;
  • Annoter la plate-forme pour fournir de meilleurs avertissements et permettre aux autres de faire de même ;
  • Sur cette base, rendre le mode d’élagage par défaut plus agressif afin qu’il soit facile de réduire la taille des applications.

L'élagage était jusqu’à présent uniquement disponible sous forme de préversion, en raison du manque de fiabilité des résultats pour les applications qui comportent ou utilisent du code faisant appel à la réflexion et non annoté comme tel. Avec les avertissements d’élagage, l’expérience devrait maintenant être reproductible. Les applications sans avertissement d’élagage devraient être découpées correctement et n’observer aucun changement de comportement lors de leur exécution. Actuellement, seules les bibliothèques .NET de base ont été entièrement annotées pour l’élagage, mais nous espérons que l’écosystème adoptera cette habitude.

Diminution de la taille d’une application

Jetons un coup d’œil à cette amélioration de l’élagage en utilisant crossgen, qui est l’un des outils du SDK. Il peut être élagué avec seulement quelques avertissements, que l’équipe de crossgen a pu résoudre.

Tout d’abord, examinons la publication de l’outil crossgen en tant qu’application autonome sans élagage. Elle fait 80 Mo (ce qui inclut le runtime .NET et toutes les bibliothèques).

publish

Nous pouvons toujours essayer le mode (désormais obsolète) de .NET 5, dénommé copyused. Le résultat descend à 55 Mio.

publish

Le nouveau mode d’élagage par défaut de .NET 6, dénommé link, réduit encore davantage la taille du fichier autonome, qui passe à 36 Mio.

publish

Nous espérons que le nouveau mode d’élagage du code lors de l'édition des liens par le compilateur correspond beaucoup mieux aux attentes en la matière : économies importantes sur l’espace disque et comportement des programmes préservés.

Avertissements activés par défaut

Les avertissements sur l’élagage du code vous indiquent les endroits où l’élagage peut supprimer du code utilisé au moment de l’exécution. Ces avertissements étaient auparavant désactivés par défaut, car ils étaient très bruyants, en grande partie parce que la plate-forme .NET n’était pas prête pour l’élagage (manque d’annotations par exemple).

Nous avons annoté de grandes parties des bibliothèques .NET afin qu’elles produisent des avertissements précis. Par conséquent, nous avons estimé qu’il était temps d’activer par défaut les avertissements sur l’élagage. Les bibliothèques liées aux runtimes ASP.NET Core et Windows Desktop n’ont pas été annotées. Nous prévoyons d’annoter ensuite les composants ASP .NET (après la publication de .NET 6). Nous espérons que la communauté annotera les bibliothèques NuGet tierces parties maintenant que .NET 6 est disponible.

Vous pouvez désactiver les avertissements en attribuant la valeur true à SuppressTrimAnalysisWarnings :

<SuppressTrimAnalysisWarnings>True</SuppressTrimAnalysisWarnings>

Plus d’informations :

Partagé avec Native AOT

Nous avons également implémenté les mêmes avertissements pour l’élagage du code au sein du projet expérimental de compilation native dénommé Native AOT.

Mathématiques

Nous avons considérablement amélioré les API mathématiques. Certaines personnes de la communauté utilisent déjà ces améliorations avec succès.

Interfaces de programmation axées sur la performance

Des API mathématiques axées sur les performances ont été ajoutées à System.Math. Leur mise en œuvre est accélérée par le matériel si le matériel sous-jacent le prend en charge.

Nouvelles interfaces de programmation

Nouvelles surcharges

Améliorations des performances

Merci à Alex Covington.

Performances sur les BigInteger

L’analyse des BigIntegers à partir de chaînes de caractères décimales et hexadécimales a été améliorée. Nous constatons des améliorations allant jusqu’à 89 %, comme le montre le graphique suivant (plus la ligne est basse plus les performances sont meilleures).

graph

Merci à Joseph Da Silva.

Interfaces de programmation garanties sans copie

Plusieurs interfaces de programmation de l’espace de noms System.Numerics.Complex sont désormais annotées comme readonly afin de garantir qu’aucune copie n’est effectuée pour les valeurs readonly ou les valeurs passées en paramètre.

Merci à hrrrrustic.

BitConverter prend désormais en charge les transformations de valeurs à virgules flottantes vers des entiers non signés

BitConverter prend en charge désormais DoubleToUInt64Bits, HalfToUInt16Bits, SingleToUInt32Bits, UInt16BitsToHalf, UInt32BitsToSingle, and UInt64BitsToDouble. Cela devrait faciliter la manipulation des bits à virgule flottante lorsque cela est nécessaire.

Merci à Michal Petryka.

BitOperations prend en charge de nouvelles fonctionnalités

BitOperations dispose désormais des interfaces de programmation IsPow2, RoundUpToPowerOf2, et fournit des surcharges nint/nuint pour les fonctions existantes.

Merci à John Kelly, Huo Yaoyuan et Robin Lindner.

Améliorations de Vector, Vector2, Vector3, et Vector4

Vector prend désormais en charge les types valeur nint et nuint, ajoutés en C# 9. Par exemple, ce changement devrait simplifier l’utilisation d’instructions SIMD avec des pointeurs ou des types de longueur dépendant de la plate-forme.

Vector prend désormais en charge la méthode Sum pour simplifier le calcul de la "somme horizontale" de tous les éléments du vecteur. Merci à Ivan Zlatanov.

Vector prend désormais en charge une méthode As générique pour simplifier le traitement des vecteurs dans des contextes génériques où le type concret n’est pas connu. Merci à Huo Yaoyuan.

Des surcharges prenant en charge Span ont été ajoutées à Vector2, Vector3 et Vector4 pour améliorer l’expérience lors du chargement ou du stockage des objets de type vecteur.

Meilleure analyse syntaxique des formats numériques standard

Nous avons amélioré l’analyseur syntaxique pour les types numériques standards, en particulier pour .ToString et .TryFormat. Ils comprennent désormais les demandes de précision > 99 décimales et fournissent des résultats précis jusqu’à ce nombre de chiffres. De plus, l’analyseur supporte mieux les zéros de fin de ligne dans la méthode Parse.

Les exemples suivants montrent le comportement avant et après.

32.ToString("C100") -> C132
  .NET 6: $32.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  .NET 5: Nous avions une limitation artificielle dans le code de formatage pour ne traiter qu'une précision de <= 99. Pour une précision >= 100, nous avons plutôt interprété l'entrée comme un format personnalisé.
32.ToString("H99") -> throw a FormatException
  .NET 6: lève une exception de type FormatException
  C'est le comportement attendu, mais il est appelé ici pour contraster avec l'exemple suivant.
32.ToString("H100") -> H132
  .NET 6: lève une exception de type FormatException
  .NET 5: H est un spécificateur de format invalide. Nous aurions donc  lever une FormatException. Au lieu de cela, notre comportement incorrect consistant à interpréter la précision >= 100 comme des formats personnalisés nous a permis de renvoyer des valeurs erronées.
double.Parse("9007199254740997.0") -> 9007199254740998
  .NET 6: 9007199254740996.
  .NET 5: 9007199254740997.0 n'est pas exactement représentable dans le format IEEE 754. Avec notre schéma d'arrondi actuel, la valeur de retour correcte aurait  être 9007199254740996. Cependant, la dernière partie .0 de l'entrée a forcé l'analyseur à arrondir incorrectement le résultat et à renvoyer 9007199254740998.

System.Text.Json

System.Text.Json fournit plusieurs API hautes performances pour le traitement des documents JSON. Au cours des dernières versions, nous avons ajouté de nouvelles fonctionnalités pour améliorer encore les performances de traitement JSON et pour faciliter la migration pour les utilisateurs de NewtonSoft.Json. Cette version continue sur cette voie et constitue une avancée majeure en termes de performances, en particulier avec le générateur de sources du sérialiseur.

Génération de code source par JsonSerializer

Remarque : les applications qui ont utilisé la génération de sources avec .NET 6 RC1 ou des versions antérieures doivent être recompilées.

L’épine dorsale de presque tous les sérialiseurs .NET est la réflexion. La réflexion est une excellente capacité pour certains scénarios, mais pas comme base d’applications cloud-native hautes performances (qui (dé)sérialisent et traitent généralement beaucoup de documents JSON). De part sa lenteur inhérente, la réflexion est un problème pour le temps de démarrage, l’utilisation de la mémoire et l'élagage du code.

L’alternative à la réflexion à l’exécution est la génération de sources à la compilation. Dans .NET 6, nous incluons un nouveau générateur de sources en tant que composant de System.Text.Json. Le générateur de sources JSON fonctionne conjointement avec JsonSerializer et peut être configuré de plusieurs façons.

Il peut offrir les avantages suivants :

  • Réduire le temps de démarrage ;
  • Améliorer le débit de sérialisation ;
  • Réduction de l’utilisation de la mémoire ;
  • Suppression de l’utilisation de System.Reflection et System.Reflection.Emit au moment de l’exécution ;
  • Compatibilité avec l’élagage du langage intermédiaire (IL).

Par défaut, le générateur de sources JSON émet une logique de sérialisation pour les types sérialisables donnés en entrée. Cela permet d’obtenir de meilleures performances qu’en utilisant les méthodes JsonSerializer existantes, en générant un code source qui utilise directement Utf8JsonWriter. En bref, les générateurs de sources offrent un moyen de vous donner une implémentation différente à la compilation afin d’améliorer les performances à l’exécution, et réduire la taille de votre application.

En considérant ce type utilisateur simple :

namespace Test
{
    internal class JsonMessage
    {
        public string Message { get; set; }
    }
}

Le générateur de sources peut être configuré pour générer une logique de sérialisation pour les instances du type JsonMessage de l’exemple. Notez que le nom de la classe JsonContext est arbitraire. Vous pouvez utiliser le nom de classe de votre choix pour le code source générée.

using System.Text.Json.Serialization;

namespace Test
{
    [JsonSerializable(typeof(JsonMessage)]
    internal partial class JsonContext : JsonSerializerContext
    {
    }
}

L’invocation du sérialiseur avec ce mode pourrait ressembler à l’exemple suivant. Cet exemple fournit les meilleures performances possibles.

using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);
JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);
writer.Flush();
// Writer contient:
// {"Message":"Hello, world!"}

Le mode de génération de sources le plus rapide et le plus optimisé – basé sur Utf8JsonWriter – n’est actuellement disponible que pour la sérialisation. Un support similaire pour la désérialisation – basé sur Utf8JsonReader – pourrait être fourni à l’avenir en fonction des retours.

Le générateur de sources émet également une logique d’initialisation des métadonnées de type qui peut également profiter à la désérialisation. Pour désérialiser une instance de JsonMessage en utilisant les métadonnées de type pré-générées, vous pouvez procéder comme suit :

JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);

Prise en charge de JsonSerializer pour IAsyncEnumerable

Vous pouvez désormais (dé)sérialiser des tableaux JSON qui peuvent être itérés de manière asynchrone au travers de l’interface IAsyncEnumerable avec System.Text.Json. Les exemples suivants utilisent des flux comme représentation de toute source de données asynchrone. La source peut être des fichiers sur une machine locale, ou les résultats d’une requête de base de données ou d’un appel API de service web.

JsonSerializer.SerializeAsync a été mis à jour pour reconnaître et fournir une manipulation spéciale pour les valeurs IAsyncEnumerable.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

static async IAsyncEnumerable<int> PrintNumbers(int n)
{
    for (int i = 0; i < n; i++) yield return i;
}

using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // Écrit sur la sortie standard {"Data":[0,1,2]}    

Les valeurs IAsyncEnumerable sont uniquement prises en charge par les méthodes de sérialisation asynchrones. Toute tentative de sérialisation à l’aide des méthodes synchrones entraînera la levée d’une exception de type NotSupportedException.

La désérialisation asynchrone a nécessité une nouvelle interface de programmation qui renvoie un IAsyncEnumerable. Nous avons ajouté la méthode JsonSerializer.DeserializeAsyncEnumerable à cette fin, comme vous pouvez le constater dans l’exemple suivant :

using System;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
    Console.WriteLine(item);
}

Cet exemple désérialise les éléments à la demande et peut être utile lors de la consommation de flux de données particulièrement conséquents. Il ne prend en charge que la lecture des tableaux JSON au niveau de la racine, bien que cela puisse être modifié à l’avenir en fonction des retours.

La méthode DeserializeAsync existante prend en charge nominalement IAsyncEnumerable, mais dans les limites de son interface de programmation ne permettant pas de recevoir un flux continu de données. Elle doit retourner le résultat final unitairement, comme vous pouvez le voir dans l’exemple suivant.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream);
await foreach (int item in result.Data)
{
    Console.WriteLine(item);
}

public class MyPoco
{
    public IAsyncEnumerable<int> Data { get; set; }
}

Dans cet exemple, le désérialiseur aura mis en mémoire tampon tout le contenu de IAsyncEnumerable avant de retourner l’objet désérialisé. En effet, le désérialiseur doit avoir consommé la totalité de la valeur JSON avant de renvoyer un résultat.

System.Text.Json : modèle objet accessible en écriture

La fonctionnalité de DOM JSON inscriptible ajoute un nouveau modèle de programmation simple et performant pour System.Text.Json. Cette nouvelle interface de programmation est intéressante, car elle évite d’avoir recours à des contrats de sérialisation fortement typés. Aussi, le DOM peut être changé (il est mutable), contrairement au type JsonDocument existant.

Cette nouvelle interface de programmation présente les avantages suivants :

  • Une alternative légère à la sérialisation pour les cas où l’utilisation de types POCO n’est pas possible ou souhaitée, ou lorsqu’un schéma JSON n’est pas fixe et doit être inspecté ;
  • Permet la modification efficace d’un sous-ensemble d’un grand arbre. Par exemple, il est possible de naviguer efficacement vers une sous-section d’un grand arbre JSON et de lire un tableau ou de désérialiser un POCO à partir de cette sous-section. LINQ peut également être utilisé conjointement.

L’exemple suivant démontre ce nouveau modèle de programmation :

// Parse un objet JSON
JsonNode jNode = JsonNode.Parse("{"MyProperty":42}");
int value = (int)jNode["MyProperty"];
Debug.Assert(value == 42);
// ou
value = jNode["MyProperty"].GetValue<int>();
Debug.Assert(value == 42);

// Parse un tableau JSON
jNode = JsonNode.Parse("[10,11,12]");
value = (int)jNode[1];
Debug.Assert(value == 11);

// ou
value = jNode[1].GetValue<int>();
Debug.Assert(value == 11);

// Créé un nouveau JsonObject en utilisant des initialiseurs d'objets et des paramètres de tableaux.
var jObject = new JsonObject
{
    ["MyChildObject"] = new JsonObject
    {
        ["MyProperty"] = "Hello",
        ["MyArray"] = new JsonArray(10, 11, 12)
    }
};

// Obtient le JSON à partir du nouveau JsonObject
string json = jObject.ToJsonString();
Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}

// Les indexeurs pour les noms de propriétés et les éléments de tableaux
// sont pris en charge et peuvent être appelés à la chaîne.
Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>() == 11);

ReferenceHandler.IgnoreCycles

JsonSerializer (System.Text.Json) prend désormais en charge la possibilité d’ignorer les références circulaires lors de la sérialisation d’un graphe d’objets. L’option ReferenceHandler.IgnoreCycles a un comportement similaire à celui de Newtonsoft.Json ReferenceLoopHandling.Ignore. Une différence essentielle est que l’implémentation faite au sein de System.Text.Json remplace les boucles de référence par null dans le JSON au lieu d’ignorer la référence d'objet.

Vous pouvez constater le comportement de ReferenceHandler.IgnoreCycles dans l’exemple suivant. Dans ce cas, la propriété Next est sérialisée en tant que null sous peine de créer une référence circulaire.

class Node
{
    public string Description { get; set; }
    public object Next { get; set; }
}
void Test()
{
    var node = new Node { Description = "Node 1" };
    node.Next = node;
    var opts = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles };
    string json = JsonSerializer.Serialize(node, opts);
    Console.WriteLine(json); // Écrit sur la sortie standard {"Description":"Node 1","Next":null}
}

Compilation à partir des sources

Avec la compilation à partir des sources, vous pouvez compiler l’entièreté du kit de développement logiciel .NET sur votre propre machine à partir des sources à l’aide de seulement quelques lignes de commandes. C’est un projet très important pour nous.

La compilation à partir des sources est un scénario et aussi une infrastructure sur lesquels nous avons travaillé en collaboration avec Red Hat avant même de livrer .NET Core 1.0. Plusieurs années plus tard, nous sommes sur le point de livrer une version entièrement automatisée de ce scénario. Pour les utilisateurs de .NET de Red Hat Enterprise Linux (RHEL), cette capacité est très importante. Red Hat nous a communiqué que .NET est devenu une plateforme de développement importante pour son écosystème. Cool !

La norme établie pour les distributions Linux est de construire du code source ouvert à l’aide de compilateurs et de chaînes d’outils qui font partie de l’archive de la distribution. Cela fonctionne pour le runtime .NET (écrit en C++), mais pas pour le code écrit en C#. Pour le code C#, nous utilisons un mécanisme de construction en deux étapes pour satisfaire aux exigences de la distro. C’est un peu compliqué, mais il est important de comprendre le flux.

Red Hat construit la source du SDK .NET en utilisant la construction binaire Microsoft du SDK .NET (étape n°1) pour produire une construction binaire open source pure du SDK (étape n°2). Ensuite, le même code source SDK est reconstruit à l’aide de cette nouvelle version du SDK (n°2) pour produire un SDK open source prouvé (n°3). Cette version binaire finale du SDK .NET (n° 3) est ensuite mise à la disposition des utilisateurs de RHEL. Après cela, Red Hat peut utiliser ce même SDK (n° 3) pour créer de nouvelles versions de .NET et n’a plus besoin d’utiliser le SDK de Microsoft pour créer des mises à jour mensuelles.

Ce processus peut être surprenant et déroutant. Les distributions open source doivent être construites par des outils open source. Ce modèle garantit que la version Microsoft du kit de développement logiciel n’est pas nécessaire, que ce soit intentionnellement ou par accident. L’exigence est plus haute, en tant que plate-forme de développement, pour être inclus dans une distro que la simple utilisation d’une licence compatible. Le projet de compilation à partir des sources a permis à .NET d’y répondre.

Le livrable pour la compilation des sources est un tarball contenant le code source. Cette archive contient toutes les sources du kit de développement logiciel (pour une version donnée). À partir de là, Red Hat (ou une autre organisation) peut construire sa propre version du kit. La politique de Red Hat exige l’utilisation d’une chaîne d’outils construite à partir des sources pour produire un tarball binaire, c’est pourquoi ils utilisent une méthode à deux passes. Mais cette méthode à deux passes n’est pas nécessaire pour la compilation des sources en elles-mêmes.

Il est courant dans l’écosystème Linux d’avoir à la fois des paquets ou des tarballs sources et binaires disponibles pour un composant donné. Nous avions déjà des tarballs binaires disponibles et nous avons maintenant des tarballs sources également. Ainsi, .NET correspond au modèle d’un composant standard sous Linux.

La grande amélioration de .NET 6 est que l’archive source est maintenant un artefact produit par la compilation. Auparavant, sa production nécessitait un effort manuel considérable, ce qui entraînait également une latence importante dans la livraison de l’archive tarball contenant les sources à Red Hat. Aucune des deux parties n’était satisfaite de cette situation.

Nous travaillons en étroite collaboration avec Red Hat sur ce projet depuis plus de cinq ans. Il a réussi, en grande partie, grâce aux efforts des excellents ingénieurs de Red Hat avec lesquels nous avons eu le plaisir de travailler. D’autres distributions et organisations ont bénéficié et bénéficieront de leurs efforts.

Par ailleurs, la compilation à partir des sources est un grand pas vers des compilations reproductibles, ce à quoi nous croyons fermement. Le kit de développement logiciel .NET et le compilateur C# disposent d’importantes capacités de compilations reproductibles.

Nouvelles interfaces de programmation dans la bibliothèque standard

Les interfaces de programmations suivantes ont été ajoutés, en plus de celles déjà décrites précédemment.

Compression WebSocket

La compression est importante pour toute donnée transmise sur un réseau. Les WebSockets permettent désormais d’utiliser la compression. Nous avons utilisé une implémentation de l’extension permessage-deflate pour WebSockets, conformément à la RFC 7692. Elle permet de compresser les charges utiles des messages WebSockets en utilisant l’algorithme DEFLATE. Cette fonctionnalité était l’une des principales demandes des utilisateurs de Networking sur GitHub.

La compression utilisée avec le chiffrement peut conduire à des attaques, comme CRIME et BREACH. Cela signifie qu’un secret ne peut pas être envoyé avec des données générées par l’utilisateur dans un contexte de compression unique, sinon ce secret pourrait être extrait. Pour attirer l’attention des utilisateurs sur ces implications et les aider à évaluer les risques, nous avons nommé l’une des API clés DangerousDeflateOptions. Nous avons également ajouté la possibilité de désactiver la compression pour des messages spécifiques, de sorte que si l’utilisateur souhaite envoyer un secret, il peut le faire en toute sécurité sans compression.

L’empreinte mémoire du WebSocket lorsque la compression est désactivée a été réduite d’environ 27 %.

L’activation de la compression du côté client est facile, comme vous pouvez le voir dans l’exemple suivant. Cependant, n’oubliez pas que le serveur peut négocier les paramètres, par exemple en demandant une fenêtre plus petite ou en refusant complètement la compression.

var cws = new ClientWebSocket();
cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions()
{
    ClientMaxWindowBits = 10,
    ServerMaxWindowBits = 10
};

La prise en charge de la compression WebSocket a aussi été rajoutée à ASP .NET Core.

Merci à Ivan Zlatanov.

Prise en charge des serveurs mandataires pour le protocole SOCKS

SOCKS est une implémentation de serveur proxy qui peut traiter tout trafic TCP ou UDP, ce qui en fait un système très polyvalent. C’est une demande de longue date de la communauté qui a été ajoutée à .NET 6.

Cette modification ajoute la prise en charge de Socks4, Socks4a et Socks5, ce qui permet par exemple de tester les connexions externes via SSH ou de se connecter au réseau Tor.

La classe WebProxy accepte désormais les schémas socks, comme vous pouvez le voir dans l’exemple suivant :

var handler = new HttpClientHandler
{
    Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);

Merci à Huo Yaoyuan.

Microsoft.Extensions.Hosting — interface de programmation ConfigureHostOptions

Nous avons ajouté une nouvelle API ConfigureHostOptions pour l’interface IHostBuilder afin de simplifier la configuration des applications (par exemple, la configuration du délai d’arrêt) :

using HostBuilder host = new()
    .ConfigureHostOptions(o =>
    {
        o.ShutdownTimeout = TimeSpan.FromMinutes(10);
    })
    .Build();
host.Run();

Précédemment avec .NET 5, sa configuration était un peu plus compliquée :

using HostBuilder host = new()
    .ConfigureServices(services =>
    {
        services.Configure<HostOptions>(o =>
        {
            o.ShutdownTimeout = TimeSpan.FromMinutes(10);
        });
    })
    .Build();
host.Run();

Microsoft.Extensions.DependencyInjection — interfaces de programmation CreateAsyncScope

L’interface de programmation CreateAsyncScope a été créée pour gérer l’élimination des services IAsyncDisposable. Auparavant, vous avez peut-être remarqué que l’élimination d’un fournisseur de service IAsyncDisposable pouvait déclencher une exception de type InvalidOperationException.

L’exemple suivant illustre la nouvelle manière d’utiliser l’interfance, en utilisant CreateAsyncScope pour permettre une utilisation sûre de l’instruction using.

await using (var scope = provider.CreateAsyncScope())
{
    var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}

Le code suivant démontre le problème qui pouvait survenir :

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

await using var provider = new ServiceCollection()
        .AddScoped<Foo>()
        .BuildServiceProvider();

// Cette ligne utilisant le mot clé using pour libérer la ressource à la fin du block peut lever InvalidOperationException
using (var scope = provider.CreateScope())
{
    var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}

class Foo : IAsyncDisposable
{
    public ValueTask DisposeAsync() => default;
}

Le code suivant permettait de contourner le problème. Il n’est plus nécessaire.

var scope = provider.CreateScope();
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
await ((IAsyncDisposable)scope).DisposeAsync();

Merci à Martin Björkström.

Microsoft.Extensions.Logging — génération de code à la compilation

.NET 6 ajoute le type LoggerMessageAttribute. Cet attribut fait partie de l’espace de noms Microsoft.Extensions.Logging et, lorsqu’il est utilisé, il génère à la source des API de journalisation à haute performance, car n’utilisant pas la réflexion. La prise en charge de la journalisation par génération de source est conçue pour offrir une solution de journalisation hautement utilisable et performante pour les applications .NET modernes. Le code source généré automatiquement s’appuie sur l’interface ILogger en conjonction avec la fonctionnalité LoggerMessage.Define.

Le générateur de sources est déclenché lorsque l’attribut LoggerMessageAttribute est utilisé sur des méthodes de journalisation partielle. Lorsqu’il est déclenché, il peut soit générer automatiquement l’implémentation des méthodes partielles qu’il décore, soit produire des diagnostics au moment de la compilation avec des indications sur l’utilisation correcte. La solution de journalisation au moment de la compilation est généralement beaucoup plus rapide au moment de l’exécution que les approches de journalisation existantes. Elle y parvient en éliminant au maximum l’unboxing (NdT : Le boxing convertit un type valeur en type référence et l’unboxing effectue l’opération inverse), les allocations temporaires et les copies.

Il existe des avantages par rapport à l’utilisation manuelle directe des interfaces de programmation LoggerMessage.Define :

  • Une syntaxe plus courte et plus simple : utilisation déclarative des attributs plutôt qu’une montagne de code sans intérêt ;
  • Une expérience guidée pour les développeurs : le générateur émet des avertissements pour aider les développeurs à faire le bon choix ;
  • Prise en charge d’un nombre arbitraire de paramètres de journalisation. LoggerMessage.Define prend en charge un maximum de six paramètres ;
  • Prise en charge du niveau de journalisation dynamique. Ceci n’est pas possible avec LoggerMessage.Define seul.

Pour utiliser l’attribut LoggerMessageAttribute, la classe et la méthode appelantes doivent être partielles. Le générateur de code est déclenché au moment de la compilation et génère une implémentation de la méthode partielle.

public static partial class Log
{
    [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Le socket vers `{hostName}` n'a pas pu être ouvert.")]
    public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
}

Dans l’exemple précédent, la méthode permettant la journalisation est statique et le niveau de journalisation est spécifié dans la définition de l’attribut. Lorsque vous utilisez l’attribut dans un contexte statique, l’instance ILogger est requise en tant que paramètre. Vous pouvez également choisir d’utiliser l’attribut dans un contexte non statique. Pour plus d’exemples et de scénarios d’utilisation, consultez la documentation du générateur de sources de journalisation à la compilation.

Langage intégré pour les requêtes (LINQ)

Depuis longtemps la communauté étend le langage de requêtes intégré grâce à des bibliothèques libres telles que MoreLINQ.
Aujourd’hui, .NET 6 étend et améliore ce même langage.

System.Linq — Prise en charge des énumérables pour les paramètres des méthodes Index et Range

La méthode Enumerable.ElementAt accepte désormais les indices à partir de la fin de l’énumérable, comme vous pouvez le voir dans l’exemple suivant :

Enumerable.Range(1, 10).ElementAt(^2); // retourne 9

Une surcharge Enumerable.Take a été ajoutée qui accepte les paramètres Range. Elle simplifie la prise de tranches de séquences énumérables :

source.Take(..3) // à la place de source.Take(3)
source.Take(3..) // à la place de source.Skip(3)
source.Take(2..7) // à la place de source.Take(7).Skip(2)
source.Take(^3..) // à la place de source.TakeLast(3)
source.Take(..^3) // à la place de source.SkipLast(3)
source.Take(^7..^3) // à la place de source.TakeLast(7).SkipLast(3).

Merci à @dixin.

System.Linq — TryGetNonEnumeratedCount

La méthode TryGetNonEnumeratedCount tente d’obtenir le compte de l’énumérable source sans forcer une énumération. Cette approche peut être utile dans les scénarios où il est utile de pré-allouer des tampons avant l’énumération, comme vous pouvez le voir dans l’exemple suivant :

List<T> buffer = source.TryGetNonEnumeratedCount(out int count) ? new List<T>(capacity: count) : new List<T>();
foreach (T item in source)
{
    buffer.Add(item);
}

TryGetNonEnumeratedCount vérifie les sources implémentant ICollection/ICollection ou tire parti de certaines des optimisations internes utilisées par Linq.

System.Linq — DistinctBy/UnionBy/IntersectBy/ExceptBy

De nouvelles variantes ont été ajoutées aux opérations de set qui permettent de spécifier l’égalité à l’aide de fonctions de sélection de clés, comme vous pouvez le voir dans l’exemple suivant :

Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}
var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }

System.Linq — MaxBy/MinBy

Les méthodes MaxBy et MinBy permettent de trouver les éléments maximaux ou minimaux à l’aide d’un sélecteur de clé, comme vous pouvez le voir dans l’exemple suivant :

var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age); // ("Ashley", 40)

System.Linq — Chunk

Chunk peut être utilisé pour découper un énumérable source en tranches d’une taille fixe, comme vous pouvez le voir dans l’exemple suivant :

IEnumerable<int[]> chunks = Enumerable.Range(0, 10).Chunk(size: 3); // { {0,1,2}, {3,4,5}, {6,7,8}, {9} }

Merci à Robert Andersson.

System.Linq — FirstOrDefault/LastOrDefault/SingleOrDefault surcharges prenant des paramètres par défaut

Les méthodes existantes FirstOrDefault/LastOrDefault/SingleOrDefault retournent default(T) si l’énumérable source est vide. De nouvelles surcharges ont été ajoutées qui acceptent qu’un paramètre par défaut soit retourné dans ce cas, comme vous pouvez le voir dans l’exemple suivant.

Enumerable.Empty<int>().SingleOrDefault(-1); // retourne -1

Merci à @Foxtrek64.

System.Linq — Nouvelle surcharge prenant en paramètres trois énumérables

La méthode Zip permet désormais de combiner trois énumérables, comme vous pouvez le voir dans l’exemple suivant :

var xs = Enumerable.Range(1, 10);
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);
foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs))
{
}

Merci à Huo Yaoyuan.

La nouvelle collection générique PriorityQueue

PriorityQueue (dans l’espace de noms System.Collections.Generic) est une nouvelle collection générique qui permet d’ajouter de nouveaux éléments avec une valeur et une priorité. À la sortie de la file d’attente, la PriorityQueue renvoie l’élément avec la valeur de priorité la plus basse. Vous pouvez considérer cette nouvelle collection comme similaire à Queue, mais chaque élément mis en file d’attente a une valeur de priorité qui affecte le comportement de la méthode Dequeue.

Le code suivant démontre le comportement de la PriorityQueue.

// créé une PriorityQueue à l'aide de nombres entiers
var pq = new PriorityQueue<string, int>();

// Ajoute des éléments et de leurs priorité associée
pq.Enqueue("A", 3);
pq.Enqueue("B", 1);
pq.Enqueue("C", 2);
pq.Enqueue("D", 3);
pq.Dequeue(); // returns "B"
pq.Dequeue(); // returns "C"
pq.Dequeue(); // soit "A" ou "D", la prédictibilité dans ce cas n'est pas garantie.

Merci à Patryk Golebiowski.

Amélioration des performances pour les dictionnaires utilisant des structs en tant que clés

CollectionsMarshal.GetValueRef est une nouvelle interface de programmation utilisant des pointeurs mémoire qui accélère la mise à jour des valeurs de structure dans les dictionnaires. Cette nouvelle interface de programmation est destinée à des scénarios de haute performance et non à un usage général. Elle renvoie une référence à la valeur de la structure, qui peut ensuite être mise à jour sur place avec les techniques habituelles.

Le code suivant démontre l’utilisation de l’interface de programmation :

ref MyStruct value = CollectionsMarshal.GetValueRef(dictionary, key);
// Retourne Unsafe.NullRef<TValue>() s'il n'existe pas; Vérifiable en utilisant Unsafe.IsNullRef(ref value)
if (!Unsafe.IsNullRef(ref value))
{
    // Mutation de la valeur sur place
    value.MyInt++;
}

Avant cette modification, la mise à jour des valeurs des dictionnaires de structure pouvait s’avérer coûteuse pour les scénarios à hautes performances (par exemple, les programmes s’exécutant sur des Superordinateurs), car elle nécessitait une consultation du dictionnaire et une copie de la structure dans la pile. Puis, après avoir modifié la structure, celle-ci était à nouveau affectée à la clé du dictionnaire, ce qui entraînait une autre opération de consultation et de copie. Cette amélioration réduit le hachage de la clé à une opération (au lieu de deux) et supprime toutes les opérations de copie de la structure.

Merci à Ben Adams.

Nouvelles structures DateOnly et TimeOnly

Elles présentent les caractéristiques suivantes :

  • Chacun représente la moitié d’un DateTime, soit uniquement la partie date, soit uniquement la partie heure ;
  • DateOnly est idéal pour les anniversaires, les jours de fête et les jours ouvrables. Il s’aligne sur le type de date de SQL Server ;
  • TimeOnly est idéal pour les réunions récurrentes, les réveils et les heures de bureau hebdomadaires. Il s’aligne sur le type d’heure de SQL Server ;
  • Complète les types de date/heure existants (DateTime, DateTimeOffset, TimeSpan, TimeZoneInfo) ;
  • Elles sont dans l’espace de noms System, livrés avec la bibliothèque standard, tout comme les types connexes existants.

Améliorations des performances de DateTime.UtcNow

Cette amélioration présente les avantages suivants :

Prise en charge à la fois des fuseaux horaires Windows et IANA sur toutes les plateformes

Les améliorations sont les suivantes :

  • Conversion implicite lors de l’utilisation de TimeZoneInfo.FindSystemTimeZoneById (https://github.com/dotnet/runtime/pull/49412) ;
  • Conversion explicite par le biais de nouvelles API sur TimeZoneInfo : TryConvertIanaIdToWindowsId, TryConvertWindowsIdToIanaId, et HasIanaId (https://github.com/dotnet/runtime/issues/49407) ;
  • Améliore la prise en charge multiplateforme et l’interopérabilité entre les systèmes qui utilisent différents types de fuseaux horaires ;
  • Supprime la nécessité d’utiliser la bibliothèque libre TimeZoneConverter. La fonctionnalité est maintenant intégrée.

Noms d’affichage des fuseaux horaires améliorés

Pour les systèmes d’exploitation Unix et apparentés, l’affichage des fuseaux horaires a été amélioré:

  • Supprime l’ambiguïté des noms d’affichage dans la liste renvoyée par TimeZoneInfo.GetSystemTimeZones ;
  • Prend avantage des données de mondialisation de l'ICU / CLDR. Pour Unix et apparentés seulement pour le moment. Windows utilise toujours les données du la Base de Registre. Cela pourra être modifié ultérieurement.

Les changements suivants ont aussi été apportés :

  • Le nom d’affichage et le nom standard du fuseau horaire UTC étaient "codés en dur" en anglais et utilise maintenant la même langue que le reste des données du fuseau horaire (CurrentUICulture sur Unix, langue par défaut du système d’exploitation sur Windows) ;
  • Les noms d’affichage des fuseaux horaires sous Wasm utilisent l'ID IANA non localisé à la place, en raison des limitations de longueur des noms ;
  • La classe imbriquée TimeZoneInfo.AdjustmentRule voit sa propriété interne BaseUtcOffsetDelta rendue publique et obtient un nouveau constructeur qui prend baseUtcOffsetDelta comme paramètre. (https://github.com/dotnet/runtime/issues/50256) ;
  • TimeZoneInfo.AdjustmentRule reçoit également diverses corrections pour le chargement des fuseaux horaires sous Unix (https://github.com/dotnet/runtime/pull/49733), (https://github.com/dotnet/runtime/pull/50131).

Prise en charge améliorée des ACL de Windows

System.Threading.AccessControl comprend désormais une prise en charge améliorée de l’interaction avec les listes de contrôle d’accès (ACLs) de Windows. De nouvelles surcharges ont été ajoutées aux méthodes OpenExisting et TryOpenExisting pour EventWaitHandle, Mutex et Semaphore. Ces surcharges – à l’aide d’instances de classes apportant des "privilèges de sécurité" – permettent d’ouvrir des instances existantes d’objets de synchronisation de fils d’exécution qui ont été créés avec des attributs de sécurité spécifiques à Windows.

Cette mise à jour correspond aux API disponibles dans le .NET Framework et présente le même comportement.

Les exemples suivants démontrent l’utilisation de ces nouvelles interfaces de programmation :

Via une Mutex

var rights = MutexRights.FullControl;
string mutexName = "MyMutexName";
var security = new MutexSecurity();

SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
MutexAccessRule accessRule = new MutexAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);

// createdMutex, openedMutex1 et openedMutex2 pointent vers la même mutex
Mutex createdMutex = MutexAcl.Create(initiallyOwned: true, mutexName, out bool createdNew, security);
Mutex openedMutex1 = MutexAcl.OpenExisting(mutexName, rights);
MutexAcl.TryOpenExisting(mutexName, rights, out Mutex openedMutex2);

Via une Semaphore

var rights = SemaphoreRights.FullControl;
string semaphoreName = "MySemaphoreName";
var security = new SemaphoreSecurity();
SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
SemaphoreAccessRule accessRule = new SemaphoreAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);
// createdSemaphore, openedSemaphore1 et openedSemaphore2 point pointent vers la même sémaphore
Semaphore createdSemaphore = SemaphoreAcl.Create(initialCount: 1,  maximumCount: 3, semaphoreName, out bool createdNew, security);
Semaphore openedSemaphore1 = SemaphoreAcl.OpenExisting(semaphoreName, rights);
SemaphoreAcl.TryOpenExisting(semaphoreName, rights, out Semaphore openedSemaphore2);

Via EventWaitHandle

var rights = EventWaitHandleRights.FullControl;
string eventWaitHandleName = "MyEventWaitHandleName";
var security = new EventWaitHandleSecurity();
SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
EventWaitHandleAccessRule accessRule = new EventWaitHandleAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);
// createdHandle, openedHandle1 et openedHandle2 pointent vers le même EventWaitHandle
EventWaitHandle createdHandle = EventWaitHandleAcl.Create(initialState: true, EventResetMode.AutoReset, eventWaitHandleName, out bool createdNew, security);
EventWaitHandle openedHandle1 = EventWaitHandleAcl.OpenExisting(eventWaitHandleName, rights);
EventWaitHandleAcl.TryOpenExisting(eventWaitHandleName, rights, out EventWaitHandle openedHandle2);

Génération de codes d’authentification de messages en un seul appel

Les classes HMAC de System.Security.Cryptography ont maintenant des méthodes statiques qui permettent le calcul en une seule fois des HMAC sans allocations mémoire. Ces ajouts sont similaires aux méthodes de génération de hachage en une seule fois qui ont été ajoutées dans une version précédente.

DependentHandle est disponible pour le code utilisateur

Le type DependantHandle n’est plus exclusif au cœur de .NET, mais disponible pour tous. Il permet l’usage de l’interface de programmation suivante :

namespace System.Runtime
{
    public struct DependentHandle : IDisposable
    {
        public DependentHandle(object? target, object? dependent);
        public bool IsAllocated { get; }
        public object? Target { get; set; }
        public object? Dependent { get; set; }
        public (object? Target, object? Dependent) TargetAndDependent { get; }
        public void Dispose();
    }
}

Il peut être utilisé pour créer des systèmes avancés, tels que des systèmes de mise en cache sophistiqués ou des versions personnalisées du type ConditionalWeakTable. Par exemple, il sera utilisé par le type WeakReferenceMessenger du MVVM Toolkit pour éviter les allocations mémoire lors de la diffusion de messages.

Un thread pool réécrit

Le thread pool de .NET a été entièrement réécrit en C# au lieu de C++ et est maintenant utilisé comme pool de threads par défaut dans .NET 6. Nous avons effectué ce changement pour permettre à toutes les applications .NET d’avoir accès à la même implémentation, indépendamment de l’utilisation de CoreCLR, Mono ou de tout autre runtime. Nous n’avons pas observé et ne prévoyons aucune mauvaise conséquence fonctionnelle ou de performance suite à ce changement.

RyuJIT

Dans cette version, l’équipe a apporté de nombreuses améliorations au compilateur .NET à la volée (JIT). documentées dans chacun des messages de publication des préversions. La plupart de ces changements améliorent les performances. Quelques-uns des points forts à propos de RyuJIT sont documentés ci-dessous.

PGO dynamique

Dans .NET 6, nous avons activé deux formes de PGO (Profile Guided Optimization) :

  • PGO dynamique utilise les données recueillies à partir de l’exécution en cours pour optimiser l’exécution en cours.
  • La PGO statique s’appuie sur les données recueillies lors des exécutions précédentes pour optimiser les exécutions futures.

La PGO dynamique a déjà été abordée dans la section sur les performances, plus haut dans ce billet.

En résumé, la PGO dynamique permet au JIT de recueillir des informations au moment de l’exécution sur les chemins et les types de code qui sont effectivement utilisés pour cette exécution spécifique de l’application. Le JIT peut alors optimiser le code en fonction de ces chemins de code pour une amélioration parfois très significative des performances. Nous avons constaté des améliorations à deux chiffres tant en test qu’en production. Il existe un ensemble de techniques de compilation classiques qui ne sont possibles ni avec un JIT ni avec la compilation en avance sur le temps sans PGO. Nous sommes maintenant en mesure d’appliquer ces techniques. Le fractionnement chaud/froid est l’une de ces techniques et la dévirtualisation en est une autre.

Pour activer la PGO dynamique, définissez DOTNET_TieredPGO=1 dans l’environnement où votre application sera exécutée.

Comme indiqué dans la section sur les performances, la PGO dynamique permet une amélioration de 26 % (510 K -> 640 K) des demandes par seconde traitées pour la suite de bancs d’essais TechEmpower JSON "MVC". C’est une amélioration importante, apportée sans aucune modification du code utilisateur.

Notre ambition est d’activer la PGO dynamique par défaut dans une prochaine version de .NET, probablement lors de la publication de .NET 7. Nous vous encourageons vivement à essayer cette fonctionnalité dans vos applications et à nous faire part de vos commentaires.

L’optimisation dynamique complète

Pour bénéficier de tous les avantages de la PGO dynamique, vous pouvez définir deux variables d’environnement supplémentaires : DOTNET_TC_QuickJitForLoops=1 et DOTNET_ReadyToRun=0. Cela permet de s’assurer qu’autant de méthodes que possible participent à la compilation par étage (Tiered Compilation). Nous appelons cette variante 'PGO complète'. La PGO complète peut fournir de plus grands avantages en termes de performance en régime permanent que Dynamic PGO mais aura des temps de démarrage plus lents (puisque plus de méthodes doivent être compilées par le JIT au niveau 0).

Vous ne voudrez pas utiliser cette option pour une application serverless dont le temps d’exécution est court, mais elle peut être utile pour une application avec un temps d’exécution long.

Dans les prochaines versions, nous prévoyons de rationaliser et de simplifier ces options afin que vous puissiez bénéficier des avantages de la PGO complète plus simplement et pour un plus grand nombre de cas d’usage.

La PGO statique

Nous utilisons actuellement la PGO statique pour optimiser les assemblages de bibliothèques .NET tels que System.Private.CoreLib qui sont livrés avec R2R (Ready To Run).

L’avantage de la PGO statique est que les optimisations sont effectuées lorsque les assemblages sont compilés au format R2R avec crossgen. Cela signifie qu’il y a un bénéfice à l’exécution sans coût supplémentaire induit lors de l’exécution de l’application. C’est très significatif pour les performances, et c’est la raison pour laquelle l’optimisation guidée par les profils est importante dans d’autres langages (comme en C++, par exemple).

Alignement des boucles

L’alignement de la mémoire est une exigence courante pour diverses opérations dans l’informatique moderne. Dans .NET 5, nous avons commencé à aligner les méthodes à la limite des 32 octets. Dans .NET 6, nous avons ajouté une fonction d’alignement adaptatif des boucles qui ajoute des instructions de remplissage NOP dans une méthode comportant des boucles, de sorte que le code de la boucle commence à l’adresse mémoire mod(16) ou mod(32). Ces modifications améliorent et stabilisent les performances du code .NET.

Dans le tableau de tri à bulles suivant, le point de données 1 représente le point où nous avons commencé à aligner les méthodes sur la limite de 32 octets. Le point de données 2 représente le point où nous avons commencé à aligner les boucles internes de la même manière. Comme vous pouvez le constater, les performances et la stabilité du banc d’essai s’améliorent considérablement.

bubble sort chart

Structures de données accélérées par le matériel

Les structures sont une partie importante du système de types du CLR. Ces dernières années, ils ont été fréquemment utilisés comme primitifs de performance dans les bibliothèques .NET. Les exemples récents sont ValueTask, ValueTuple et Span. Les structs d’enregistrement en sont un nouvel exemple. Dans .NET 5 et .NET 6, nous avons amélioré les performances des structs, en partie en veillant à ce que les structs puissent être maintenus dans des registres ultra-rapides du CPU lorsqu'elles sont des variables locales, des arguments ou des valeurs de retour de méthodes. Ceci est particulièrement bénéfique pour les API qui utilisent des vecteurs pour leurs calculs.

Stabiliser les mesures de performance

L’équipe effectue une quantité énorme de travail sur les systèmes d’ingénierie qui n’apparaît jamais sur le blog. Cela est vrai pour tout produit matériel ou logiciel que vous utilisez. L’équipe JIT a entrepris un projet visant à stabiliser les mesures de performance dans le but d’accroître la valeur des régressions signalées automatiquement par l’automatisation de notre laboratoire de performance interne. Ce projet est intéressant en raison de l’enquête approfondie et des changements qui ont été nécessaires pour permettre la stabilité. Il démontre également l’échelle à laquelle nous mesurons pour maintenir et améliorer les performances.

performances améliorées

Cette image montre des mesures de performance instables où la performance a fluctué entre le lent et le rapide lors de passages successifs. L’axe des x est la date du test et l’axe des y est le temps du test en nanosecondes. À la fin du graphique (après que ces changements aient été effectués), vous pouvez voir que les mesures se sont stabilisées, avec le meilleur résultat. Cette image montre un seul test. Il y a beaucoup d’autres tests qui ont un comportement similaire à l’adresse suivante dotnet/runtime #43227.

Code Ready-to-run (R2R) / Crossgen 2

Lorsque vous créez un programme (ou assembly en anglais) .NET à l’aide du compilateur C#, votre assemblage ne contient que du code en langage intermédiaire (MSIL, ou IL). Lorsque l’application s’exécute, le compilateur Juste à Temps traduit le code MSIL en code natif, avant que le processeur central ne puisse les exécuter. Ce modèle d’exécution présente certains avantages. Par exemple, votre code d’assemblage peut être portable sur toutes les plates-formes et architectures qui prennent en charge .NET. Toutefois, cette portabilité a un coût en termes de performances. Votre application démarre plus lentement, car le compilateur JIT doit passer du temps à traduire le code.

Pour accélérer le démarrage de votre application, CoreCLR (le runtime de .NET) comprend un outil appelé CrossGen, qui peut précompiler le code intermédiaire en code natif.

Crossgen2 est un remplacement de l’outil crossgen. Il est destiné à satisfaire deux objectifs :

  • Rendre le développement de crossgen plus efficace ;
  • Rendre possible un ensemble de capacités qui ne sont pas actuellement possibles avec crossgen.

Cette transition est quelque peu similaire au passage du code natif produit par l’ancien compilateur C# (csc.exe) de .NET Framework au code managé du compilateur Roslyn. Crossgen2 est lui aussi écrit en C#, mais il n’expose pas une API sophistiquée comme le fait Roslyn.

Il y a peut-être une demi-douzaine de projets que nous avions/avons planifiés pour .NET 6 et 7 qui dépendent de Crossgen2. La Pull Request pour les instructions vectorielles par défaut est un excellent exemple des possibilités offertes par crossgen2 et des changements en profondeur que nous voulions introduire pour .NET 6 mais qui seront plus probablement pour .NET 7. Les "bulles de version" sont un autre bon exemple.

Crossgen2 permet la compilation croisée (d’où le nom "crossgen") à travers les dimensions du système d’exploitation et de l’architecture. Cela signifie que vous serez en mesure d’utiliser une seule machine de compilation pour générer du code natif pour toutes les cibles, du moins en ce qui concerne le code prêt à être exécuté. L’exécution et le test de ce code est une autre histoire, cependant, et vous aurez besoin du matériel et des systèmes d’exploitations appropriés pour cela.

La première étape consiste à compiler la plate-forme .NET elle-même avec crossgen2. Nous l’avons fait avec .NET 6, pour toutes les architectures. En conséquence, nous avons pu retirer l’ancien outil crossgen de cette version. Notez que crossgen2 ne s’applique qu’à CoreCLR et non aux applications basées sur Mono (qui ont un ensemble distinct d’outils de génération de code).

Ce projet – du moins au début – n’est pas orienté sur la performance. L’objectif est de permettre une bien meilleure architecture pour héberger le compilateur RyuJIT (ou tout autre compilateur) afin de générer du code d’une manière hors ligne (sans nécessiter de démarrer le runtime).

Vous pourriez dire "hé… ne devez-vous pas lancer le runtime pour exécuter crossgen2 s’il est écrit en C# ?". Oui, mais ce n’est pas ce que l’on entend par "hors ligne" dans ce contexte. Lorsque crossgen2 s’exécute, nous n’utilisons pas le JIT fourni avec le runtime sur lequel crossgen2 s’exécute pour générer du code prêt à l’emploi (R2R). Cela ne fonctionnera pas, du moins pas avec les objectifs que nous avons. Imaginez que crossgen2 tourne sur une machine x64, et que nous devons générer du code pour Arm64. Crossgen2 charge le RyuJIT Arm64 – compilé pour x64 – comme un plugin natif, et l’utilise ensuite pour générer du code R2R Arm64. Les instructions machine ne sont qu’un flux d’octets qui sont enregistrés dans un fichier. Cela peut aussi fonctionner dans le sens inverse. Sur Arm64, crossgen2 peut générer du code x64 en utilisant le RyuJIT x64 compilé sur Arm64. Nous utilisons la même approche pour cibler du code x64 sur des machines x64. Crossgen2 charge un RyuJIT construit pour n’importe quelle configuration nécessaire. Cela peut sembler compliqué, mais c’est le genre de système qu’il faut mettre en place si l’on veut permettre un modèle de ciblage croisé sans faille, et c’est exactement ce que nous voulons.

Nous espérons utiliser le terme "crossgen2" pour une seule version, après quoi il remplacera le crossgen existant, et ensuite nous reviendrons à l’utilisation du terme "crossgen" pour "crossgen2".

Diagnostiques .NET : EventPipe

EventPipe est notre mécanisme multiplateforme de sortie des événements, des données de performance et des compteurs, que ce soit en cours de traitement ou hors traitement. À partir de .NET 6, nous avons changé l’usage de C++ pour l’implémentation de l’outil par du C. Désormais et avec ce changement, Mono utilise également EventPipe. Cela signifie que CoreCLR (le runtime commun) et le runtime Mono utilisent tous deux la même infrastructure événementielle, y compris les outils en ligne de commande .NET Diagnostics.

Ce changement s’accompagne également d’une légère réduction de la taille de CoreCLR (11552 octets en moins pour libcoreclr.so)

Nous avons également apporté quelques modifications pour améliorer le débit du EventPipe lorsqu’il est en cours d’utilisation. Au cours des premières versions preview de .NET 6, nous avons effectué une série de modifications qui ont permis d’améliorer le débit de 2,06 fois par rapport à celui de .NET 5 :

eventPipe
Plus haut est considéré comme meilleur pour ce banc d’essai. .NET 5 est la ligne bleue, et .NET 6 la ligne orange.

Kit de développement logiciel

Les changements suivants ont été apportés au kit de développement logiciel .NET :

Installations des charges de travail via la ligne de commande

.NET 6 apporte le concept de charges de travail au sein du kit de développement. Les charges de travail sont des composants facultatifs qui peuvent être installés au-dessus du kit de développement .NET pour permettre divers cas d’usage. Les nouvelles charges de travail de .NET 6 sont : .NET MAUI et les charges de travail AOT de Blazor WebAssembly. Nous allons probablement créer de nouvelles charges de travail (éventuellement à partir du SDK existant) dans .NET 7. Le plus grand avantage des charges de travail est la réduction de la taille et l’aspect modulaire. Nous voulons réduire la taille du kit de développement au fil du temps et permettre d’installer uniquement les composants dont vous avez besoin. Ce modèle sera bon pour les machines des développeurs et encore meilleur pour l’intégration continue.

Les utilisateurs de Visual Studio n’ont pas vraiment à s’inquiéter des charges de travail. La fonctionnalité des charges de travail a été conçue pour qu’un orchestrateur d’installation comme Visual Studio puisse installer des charges de travail pour vous. Les charges de travail peuvent être gérées directement via la ligne de commande.

La fonctionnalité des charges de travail expose plusieurs verbes pour gérer les charges de travail, y compris les suivants :

  • dotnet workload restore – installe les charges de travail requises par un projet donné ;
  • dotnet workload install – installe une charge de travail nommée ;
  • dotnet workload list – liste les charges de travail que vous avez installées ;
  • dotnet workload update – met à jour toutes les charges de travail installées avec la dernière version disponible.

Le verbe update interroge nuget.org pour obtenir les manifestes de charges de travail mis à jour, met à jour les manifestes locaux, télécharge les nouvelles versions des charges de travail installées, puis supprime toutes les anciennes versions d’une charge de travail. Ceci est analogue à apt update && apt upgrade -y (utilisés sur les distributions Linux basées sur Debian). Il est censé de considérer les charges de travail comme un gestionnaire de paquets privé pour le kit de développement. Il est privé dans le sens où il n’est disponible que pour les composants du kit de développement. Nous pourrions reconsidérer cela à l’avenir.

Les commandes dotnet workloads fonctionnent dans le contexte du kit de développement local. Imaginez que vous ayez installé à la fois .NET 6 et .NET 7. Les commandes workloads fourniront des résultats différents pour chaque kit de développement puisque les charges de travail seront différentes (au moins différentes versions des mêmes charges de travail).

Notez que dotnet workload install copie les charges de travail de NuGet.org dans votre installation du kit de développement. Il faudra donc l’exécuter avec des droits privilégiés ou utiliser sudo si l’emplacement de l’installation est protégé (c’est-à-dire à un emplacement admin/root).

Vérification de la version intégrée

Pour savoir plus rapidement quels kits de développement et runtimes sont disponibles, nous avons ajouté une nouvelle commande au kit de développement .NET 6 :

dotnet sdk check

Il vous indique si une version plus récente est disponible pour les kits de développement, les moteurs d’exécution ou les charges de travail .NET que vous avez installés. Vous pouvez voir la nouvelle expérience dans l’image suivante.
sdk check

dotnet new

Vous pouvez désormais rechercher de nouveaux modèles sur NuGet.org avec dotnet new --search.

Parmi les autres améliorations apportées à l’installation des modèles, citons la prise en charge de l’option --interactive pour la prise en charge des informations d’autorisation pour les flux NuGet privés.

Une fois les modèles de ligne de commande installés, vous pouvez vérifier si des mises à jour sont disponibles via --update-check et --update-apply.

Validation de paquet NuGet

Les outils de validation des paquets permettent aux développeurs de bibliothèques NuGet de valider que leurs paquets sont cohérents et bien formés.

Cela comprend :

  • La vérification qu’il n’y a pas de changements incompatibles entre les versions ;
  • Vérifie que le paquet a le même ensemble d’interfaces de programmation pour toutes les implémentations spécifiques à un runtime (comme par un exemple un paquet ciblant à la fois .NET Core 3.1 et .NET 6) ;
  • Déterminer les éventuelles incompatibilités d’usage entre les différents cadriciels et runtimes.

Cet outil fait partie du kit de développement logiciel. La façon la plus simple de l’utiliser est de définir une nouvelle propriété dans votre fichier de projet :

<EnablePackageValidation>true</EnablePackageValidation>

Davantage d’analyseurs de code

Dans .NET 5, nous avons livré environ 250 analyseurs avec le SDK .NET. Beaucoup d’entre eux existaient déjà, mais étaient livrés en dehors du SDK sous forme de paquets NuGet. Nous avons ajouté d’autres analyseurs pour .NET 6.

Pour rappel, un analyseur de code a pour but de produire des suggestions sur le code en cours de développement. Lors de la compilation, le compilateur Roslyn fait appel aux analyseurs.

Par défaut, la plupart des nouveaux analyseurs sont activés au niveau Info. Vous pouvez activer ces analyseurs au niveau Warning en configurant le mode d’analyse comme suit :

<AnalysisMode>All</AnalysisMode>

Nous avons publié l’ensemble des analyseurs que nous voulions pour .NET 6 (plus quelques extras) et avons ensuite mis la plupart d’entre eux à disposition pour implémentation. La communauté a ajouté plusieurs analyseurs, dont ceux ci-dessous :

Contributeurr   Identifiant                     Titre
Newell Clark    dotnet/runtime #33777   Utiliser la variante de string.Concat reposant sur Span
Newell Clark    dotnet/runtime #33784   Préférez string.AsSpan() à string.SubString() dans vos analyses de chaînes
Newell Clark    dotnet/runtime #33789   Redéfinissez Stream.ReadAsync/WriteAsync
Newell Clark    dotnet/runtime #35343   Remplacez Dictionary<,>.Keys.Contains par ContainsKey
Newell Clark    dotnet/runtime #45552   Utilisez String.Equals au lieu de String.Compare
Meik Tranel     dotnet/runtime #47180   Utilisez String.Contains(char) au lieu de String.Contains(String)

Merci à Meik Tranel et à Newell Clark.

Utiliser des protections supplémentaires pour un code multiplateforme

L’analyseur de compatibilité de plate-forme (règle CA1416) reconnaît déjà les protections de plate-forme à l’aide des méthodes inOperatingSystem et RuntimeInformation, telles que OperatingSystem.IsWindows et OperatingSystem.IsWindowsVersionAtLeast. Cependant, l’analyseur ne reconnaît pas d’autres possibilités de protection contre du code non-multiplateforme comme le résultat de la vérification de la plate-forme mis en cache dans un champ ou une propriété, ou une logique complexe de vérification de la plate-forme définie dans une méthode d’aide.

Pour permettre d’étendre les protections existantes, nous avons ajouté de nouveaux attributs SupportedOSPlatformGuard et UnsupportedOSPlatformGuard pour annoter les membres d’une classe participant à la protection avec le nom et/ou la version de la plate-forme correspondante. Cette annotation est reconnue et respectée par l’analyseur de compatibilité de plate-forme.

Utilisation

// L'attribut spécifiant une plateforme non prise en charge.
[UnsupportedOSPlatformGuard("browser")]
#if TARGET_BROWSER
    internal bool IsSupported => false;
#else
   internal bool IsSupported => true;
#endif

[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }

void M1()
{
   // Avertissement: Ce site d'appel est atteignable sur toutes les plateforms
   // 'ApiNotSupportedOnBrowser()' est non pris en charge sur la plateforme : 'browser'
    ApiNotSupportedOnBrowser();  
    if (IsSupported)
    {
        // Pas d'avertissement
        ApiNotSupportedOnBrowser();
    }
}

[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }

[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();

void M2()
{
    // Avertissement:
    // Ce site d'appel est atteignable sur toutes les plateformes
    // 'ApiOnlyWorkOnWindowsLinux()' est pris en charge seulement sur : 'Linux', 'Windows'.
    ApiOnlyWorkOnWindowsLinux(); 
    if (_isWindowOrLinux)
    {
        // Pas d'avertissement
        ApiOnlyWorkOnWindowsLinux();
    }
}

Le mot de la fin (ouf !)

Il s’agit d’une nouvelle version importante de .NET, avec des améliorations presque équivalentes en termes de performances, de fonctionnalités, de convivialité et de sécurité. Nous espérons que vous trouverez de nombreuses améliorations qui vous rendront plus efficace et plus compétent dans votre développement quotidien et qui augmenteront les performances ou réduiront les coûts de vos applications en production. Nous avons déjà commencé à recevoir de bons retours de la part de ceux d’entre vous qui ont déjà commencé à utiliser .NET 6.

Chez Microsoft, nous sommes également dans les premières phases du déploiement de .NET 6, avec quelques applications clés déjà en production et beaucoup d’autres à venir dans les semaines et mois à venir.

.NET 6 est notre dernière version LTS à ce jour. Nous encourageons tout le monde à passer à cette version, en particulier si vous utilisez .NET 5. Nous pensons qu’il s’agit de la version de .NET la plus rapidement adoptée.

Cette version est le résultat du travail d’au moins 1000 personnes (mais probablement beaucoup plus). Il s’agit notamment de l’équipe .NET de Microsoft et de nombreux autres membres de la communauté. J’ai essayé d’inclure dans ce billet de nombreuses fonctionnalités apportées par la communauté. Merci à la communauté d’avoir pris le temps de les créer et de suivre notre processus de travail. J’espère que l’expérience a été gratifiante et qu’encore plus de personnes contribueront.

Ce billet est le fruit de la collaboration de nombreuses personnes talentueuses. Les contributions comprennent la liste des fonctionnalités que l’équipe maintient tout au long de la conception de chaque version, ainsi que beaucoup de contenu important créé pour ce présent billet, et une tonne de corrections techniques et de prose qui sont nécessaires pour arriver à une qualité finale satisfaisante. Ce fut un plaisir de rédiger ce billet et tous les précédents pour vous.

Merci à vous d’être un développeur .NET.

Remerciements

Merci à Richard Lander, l’auteur originel de cet article sur le blog officiel de Microsoft, d’avoir donné son accord pour la création de cette traduction.

Elle a été améliorée par davantage de liens et d’explications.

Aller plus loin

  • # Publicité mensongère éhontée ?!!

    Posté par  . Évalué à 5. Dernière modification le 26 décembre 2021 à 02:18.

    La dernière version du cadriciel libre (sous licence MIT)

    Wikipédia semble dire le contraire. Quelqu'un a vérifié les dépendances ? Nan, ne perdez pas de temps avec ce GAFAM, il y a tellement mieux à faire…

    Chez Microsoft, nous sommes […]
    Visual Studio 2022 [logiciel non libre] est aussi désormais disponible. […]
    Merci à Richard Lander, l’auteur originel de la dépêche sur le blog officiel [de Microsoft]

    Bref, une publicité venant de chez Microsoft. Cela a-t-il sa place sur LinuxFR ?

    Non, Microsoft n'a pas changé, c'est toujours l'ennemi de l'humanité, asservissant des centaines de millions d'utilisateurs avec des logiciels non libres (XBox, Microsoft Windows, Microsoft Office, Microsoft Teams, Microsoft Azur, etc.) et abusant de monopoles artificiels déloyaux.

    Alors oui, des boites font parfois la publicité de l'un de leur produit open source sur LinuxFR, mais jamais aucune n'a eu un profil aussi dégénéré ! Un modérateur peut-il donner un début d'explication ? :-<

    Stop à la pollution par les GAFAM de LinuxFR et du monde libre, étique et loyal.

    Merci à vous d’être un développeur .NET.

    Non merci. Ne vous laissez pas piéger, fuyez, il y a tellement mieux à faire !

    • [^] # Re: Publicité mensongère éhontée ?!!

      Posté par  (site web personnel) . Évalué à 10. Dernière modification le 26 décembre 2021 à 09:11.

      https://en.m.wikipedia.org/wiki/.NET est plus à jour. Ou https://github.com/dotnet/core

      Il s'agit d'une traduction, avec autorisation, donc on ne va pas changer le texte.

      Ça n'empêche pas d'ajouter une note de modération ce qui est désormais fait.

      • [^] # Re: Publicité mensongère éhontée ?!!

        Posté par  (site web personnel) . Évalué à 10.

        Tient, je n'arrive pas à distinguer la note de modération ? En tout cas la formulation dans la dépêche :

        « Merci à Richard Lander, l’auteur originel de la dépêche sur le blog officiel, d’avoir donné son accord pour la création de cette traduction. »

        Me semble plus qu'équivoque, même si porteuse d'un hyper lien qui permettrait de trouver le loup. C'est l'emploi d'un article définit qui choque ici. Une bonne traduction ne devrait-elle pas s'adapter à son contexte ? Est-ce que :
        « Merci à Richard Lander, l’auteur originel de cette dépêche sur un blog officiel de mirosoft, d’avoir donné son accord pour la création de cette traduction. » ne serait pas plus clair, même pour les miros ?

        Au cas où il y en ait, de précédents contenus publiés ici indiquent clairement dans quoi rentrent ceux qui s'associent à ce genre de technologie miroir aux alouettes. Dès la sortie de la chose, les gens y voyaient clair.
        On a encore un bel exemple bien récent, illustrant en pratique ce à quoi s'exposent les naïfs qui se confient dans les mains de puissances pour lesquelles ils ne sont guère plus que des outils quand ils ne sont pas vus comme des parasites.
        Sérieusement, n'y a-t-il pas pléthore d'outils de programmation aux écosystèmes moins dangereux, voire libres, pour que chacun puisse trouver chaussure à son pied sans mettre ainsi en danger ses projets en les soumettant à l'épée de Damoclès du parangon de l'EEE ?

        « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

        • [^] # Re: Publicité mensongère éhontée ?!!

          Posté par  (site web personnel) . Évalué à 6.

          Clarification du remerciement, s'il en était besoin.

        • [^] # Re: Publicité mensongère éhontée ?!!

          Posté par  . Évalué à 6.

          Sérieusement, n'y a-t-il pas pléthore d'outils de programmation aux écosystèmes moins dangereux, voire libres, pour que chacun puisse trouver chaussure à son pied sans mettre ainsi en danger ses projets en les soumettant à l'épée de Damoclès du parangon de l'EEE ?

          Il n'y a rien de dangereux, et c'est tout aussi libre que le reste.

          La licence le prouve.

          Ou alors, il va falloir argumenter avec plus que du FUD de bas étage.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Publicité mensongère éhontée ?!!

            Posté par  . Évalué à 3.

            Il y a une impérieuse nécessité à ne pas utiliser DotNet6. Parce qu'à chaque fois qu'un développeur fait ce mauvais choix, cela renforce l'emprise de Microsoft, contamine des utilisateurs et concourt à empêcher les alternatives de mieux exister.

            Car le sujet principal est la liberté. Si aujourd'hui Microsoft est obligé de faire un peu d'open source, c'est parce que des gens ont mené combat, pour la liberté. Si on avait laisser faire Microsoft, il n'y aurait plus moyen d'écrire une boucle dans un programme sans leur autorisation ou sans leur payer des droits.

            La puissance financière des GAFAM créé un déséquilibre monumentale avec le reste du monde. Il est urgent d'arrêter de le soutenir et pire, de rendre dépendant les utilisateurs de vos logiciels. C'est possible, le monde des logiciels libres connait de nombreux acteurs éthiques et loyaux, donnez leur une place, une chance, participez à leur essor. Le combat pour la liberté continue.

            Ne pas avoir conscience de ça, c'est passer à côté de tout et mettre en danger la liberté.

            • [^] # Re: Publicité mensongère éhontée ?!!

              Posté par  . Évalué à 5.

              de rendre dépendant les utilisateurs de vos logiciels.

              En quoi utiliser dotnet rend ton logiciel dépendant, vu que c'est entièrement libre ?

              Tu peux le builder entièrement toi-même, faire un fork, et tu en as le droit légal, et tout est documenté pour ce faire. Il n'y a pas plus indépendant. As-tu seulement lu la dépêche (genre la section sur les reproductible builds) ? Savais tu que les gens avaient déjà réalisé des forks pour leurs propres besoins, sans aucun problème ?

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: Publicité mensongère éhontée ?!!

                Posté par  (site web personnel) . Évalué à 10.

                Microsoft peut à tout moment "fermer" .NET. C'est un risque à prendre en compte quand tu fais des projets de très long terme.

                Le risque existait aussi avec Java avec Sun puis Oracle, mais la multiplication des jvms a montré que l'écosystème résiste pas trop mal aux tentatives de fermeture (les bibliothèques non libres de l'Oracle JDK ont des équivalents libres pour l'openjdk).

                Qu'en est-il avec .NET ?

                Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

              • [^] # Re: Publicité mensongère éhontée ?!!

                Posté par  (site web personnel) . Évalué à 8.

                « Il n'y a pas plus indépendant. »

                Là vous tenez probablement une information intéressante pour traiter les œdèmes d'E³ que cette traduction a provoqué chez les plus sensibles.

                Quel genre de gouvernance dans ce projet ? Comment s'est faite la transition vers une indépendance totale — pour les ingénus comme moi qui croient encore y discerner l'empreinte dé Bill ? Est-ce vraiment indépendant et conduit par des entités ayant à cœur le libre ? Ou bien est-ce que ça n'est pas un attrape cou mouches ?

                « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

                • [^] # Re: Publicité mensongère éhontée ?!!

                  Posté par  . Évalué à 7. Dernière modification le 28 décembre 2021 à 10:17.

                  Comment s'est faite la transition vers une indépendance totale — pour les ingénus comme moi qui croient encore y discerner l'empreinte dé Bill ?

                  .NET Core est né des sources du runtime multiplateforme écrit à l'époque pour Silverlight. Dans le nom, 'Core' dénotait cet aspect réduit de l'implémentation par rapport au .NET Framework historique.

                  En termes de gouvernance de la part de MS garantissant l'aspect libre et outre la licence et les sources ouvertes, il y a notamment (difficile de tout citer sans y passer la journée) :

                  • La .NET Foundation et son Code de Conduite
                  • Des guides pour les contributions open-source
                  • Un triage et une catégorisation des issues crées par les employés ou la communauté. Comme par exemple 'up-for-grabs' ou 'good-first-issue'
                  • Un effort pour baisser la barrière à l'entrée (réimplémentations du coeur - comme le ThreadPool - entièrement en C# plutôt qu'en C++, documentations, tutoriels, …)

                  Cependant, il ne faut pas se leurrer, .NET est un projet massif et sans MS derrière je doute que ça bougerait autant. Forker ne serait pas une mince affaire. C'est libre, mais c'est un projet qui occupe des centaines de personnes à temps plein - qu'elles soient employées par Microsoft ou non.

                  Ou bien est-ce que ça n'est pas un attrape cou mouches ?

                  Pour moi la preuve la plus éclatante est l'implication énorme de la communauté, et l'implication de MS envers cette communauté. Beaucoup de contributions (et 'beaucoup' c'est vraiment pas rendre justice au nombre de contributions) de la communauté se retrouvent dans dotnet dans son ensemble (comme par exemple les ajouts à LINQ et d'autres contributions évoquées dans cette dépêche - et bien d'autres sont décrites sur le blog dotnet de MS).

                  Quant à l'implication de MS envers la communauté, les expérimentations et le sondage pour savoir si l'AOT devait se faire ou non en sont un exemple flagrant. J'ai moi-même répondu, comme beaucoup d'autres, à ce sondage.

                  Et du coup, la compilation AOT, qui était d'abord juste une expérimentation, est dans les plans pour le futur :
                  https://github.com/dotnet/runtime/issues/61231

                  Aujourd'hui, les annotations pour l'élagage et les Source Generators en sont les prémisses (l'usage de la réflexion empêche l'usage de la compilation AOT, et l'élagage du langage intermédiaire, et les Source Generators évitent d'utiliser la réflexion)

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

        • [^] # Re: Publicité mensongère éhontée ?!!

          Posté par  . Évalué à 3.

          On a encore un bel exemple bien récent, illustrant en pratique ce à quoi s'exposent les naïfs qui se confient dans les mains de puissances pour lesquelles ils ne sont guère plus que des outils quand ils ne sont pas vus comme des parasites.

          Ils avaient des explications et ont écouté leur communauté. Des problèmes de gouvernance tu en a aussi dans des projets libres tu sais. On a des exemples encore plus récents et qui n'est pas encore terminé (mais on peut en citer d'autres encore, hein ? regarde tzdata toujours pour cette année). Sachant que la critique qui a était faite à .Net on l'a déjà entendu pour Firefox ce dangereux navigateur qui voit les linuxiens comme des parasites.

          Sérieusement, n'y a-t-il pas pléthore d'outils de programmation aux écosystèmes moins dangereux, voire libres[…]

          Dont .Net ;)

          https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: Publicité mensongère éhontée ?!!

      Posté par  . Évalué à 5.

      J'avoue maintenant que j'ai tout traduit je peux enfin sortir le popcorn !

      Joyeux Noël !

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Publicité mensongère éhontée ?!!

      Posté par  . Évalué à 7.

      Quelqu'un a vérifié les dépendances ? Nan, ne perdez pas de temps avec ce GAFAM, il y a tellement mieux à faire…

      Ça parle à 90% du langage avec, oui, quelques références à l'IDE qui lui est propriétaire.

      DotNet est développé principalement par un GAFAM mais si la licence est libre, les sources avec et que des binaires sont dispos pour accélérer les phases de CI/CD alors tant mieux !

      J'ai basculé depuis 10 ans vers du Microsoft avec C# de force au boulot. Avec ce recul, je trouve que c'est un langage vraiment incroyable avec une syntaxe élégante qui permet de presque tout faire.

      Depuis un an maintenant, grâce aux efforts des développeurs d'avoir un sdk et un runtime sous linux, je suis repassé sous debian sur mes serveurs de production. Linux reste mon OS serveur préféré pour tout un tas de bonnes raisons…

      • [^] # Re: Publicité mensongère éhontée ?!!

        Posté par  . Évalué à 6.

        J'ai aussi découvert le langage pour le boulot et bien accroché. Récemment je voulais écrire un bot Twitter, et j'hésitais sur le langage à utiliser. Je me suis dit que c'était peut-être l'occasion d'essayer de faire du C# sous Linux. J'ai essayé d'installer ce qui me semblait être l'IDE par défaut pour C# sous Linux, à savoir MonoDevelop. Plus développé depuis 2 ans, plus disponible dans les dépôts de ma distribution, sur le site on propose de télécharger des paquets pour Ubuntu 18.04 et rien de plus récent…
        Le projet a en fait été « transformé » en Visual Studio For Mac, puis tué en 2018.
        J'ai vaguement essayé d'utiliser Visual Studio Code, pas réussi à le configurer correctement, et du coup j'ai codé mon bot en Javascript.
        C'est plutôt triste.

        LinuxFr, parfois c'est bien de la MERDE : https://linuxfr.org/users/c2462250/journaux/ecriture-inclusive-feministes-et-wikipedia#comment-1793140

        • [^] # Re: Publicité mensongère éhontée ?!!

          Posté par  . Évalué à 5. Dernière modification le 26 décembre 2021 à 17:21.

          Personnellement sous Linux je ne jure que par Rider. C'est vraiment un bel IDE pour .NET.

          Pour VSCode et dotnet, il y a des tutoriels. Exemple :

          https://docs.microsoft.com/en-us/dotnet/core/tutorials/debugging-with-visual-studio-code?pivots=dotnet-6-0

          Sinon ça s'écrit très vite avec (par exemple) vim allié omnisharp-vim pour la complétion et le déboguage, et le sdk dotnet. Exemple :

          1. Je suis sous Debian ou autre
          2. J'installe le sdk dotnet depuis les dépôts de ma distribution ou depuis le dépôt Microsoft
          3. Je me mets dans un nouveau dossier
          4. Un petit 'git init'
          5. Un petit 'dotnet new console' (pour un programme en ligne de commande)
          6. Je modifie Program.cs
          7. Je sais utiliser les différentes actions suivantes:
          • dotnet run pour lancer l'appli à l'aide du SDK .NET, sans devoir compiler d'abord (la commande s'en occupe)
          • dotnet build pour compiler
          • dotnet publish -c Release pour compiler une version à publier

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Publicité mensongère éhontée ?!!

            Posté par  . Évalué à 4.

            Merci pour le conseil. J'essaierais bien Rider, malgré qu'il soit propriétaire, mais en plus il semble être payant. Gratuit pour un projet opensource… mais si je ne peux pas commencer par tester tranquillement, je vais difficilement me lancer dans un gros projet.

            Pour VS Code, je crois que le problème était peut-être lié au fait d'avoir installé les paquets "mono" et "mono-tools" au lieu de "dotnet-sdk" ?
            J'étais resté à l'idée que C# sous Linux c'était Mono.
            J'avais réussi à compiler un programme exemple depuis mon terminal avec
            mcs gtk-helloworld.cs -pkg:gtk-sharp-2.0
            mais dans Visual Studio Code, je n'arrivais à rien.

            LinuxFr, parfois c'est bien de la MERDE : https://linuxfr.org/users/c2462250/journaux/ecriture-inclusive-feministes-et-wikipedia#comment-1793140

            • [^] # Re: Publicité mensongère éhontée ?!!

              Posté par  . Évalué à 5.

              Vscode + dotnet sdk + l'extension C# pour vscode suffisent.

              Il n'y a pas besoin de Mono.

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: Publicité mensongère éhontée ?!!

                Posté par  . Évalué à 2.

                Noté, merci. La prochaine fois que j'aurais une belle occasion de coder quelque chose dans un nouveau langage j'essaierais sans doute comme ça, et si tout se passe bien j'essaierais aussi Rider !

                LinuxFr, parfois c'est bien de la MERDE : https://linuxfr.org/users/c2462250/journaux/ecriture-inclusive-feministes-et-wikipedia#comment-1793140

    • [^] # Re: Publicité mensongère éhontée ?!!

      Posté par  . Évalué à 8. Dernière modification le 26 décembre 2021 à 14:36.

      Wikipédia semble dire le contraire. Quelqu'un a vérifié les dépendances ? Nan, ne perdez pas de temps avec ce GAFAM, il y a tellement mieux à faire…

      Ah non c'est bien lire et tout sur GitHub :

      https://github.com/dotnet/

      C'est bien la licence MIT :
      https://github.com/dotnet/runtime/blob/main/LICENSE.TXT

      Et c'est même fait avec des builds reproductibles, (voir le paragraphe "De l'importance de Debian"), donc il est où le problème ?

      Moi je pense que le problème c'est que certains n'ont pas évolué depuis la fin des années 90.

      Bref, une publicité venant de chez Microsoft. Cela a-t-il sa place sur LinuxFR ?

      Tu sais, avec la ligne de commande dotnet et vim, ça marche tout aussi bien.
      Ou VSCodium.
      Ou tout ce que tu veux.

      Non merci. Ne vous laissez pas piéger, fuyez, il y a tellement mieux à faire !

      C'est libre et open-source, avec une communauté plus que conséquente. C'est interdit sur LinuxFR ?

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: Publicité mensongère éhontée ?!!

        Posté par  . Évalué à 10.

        Bonjour,

        Pour commencer, je suis dev dot.net depuis plus de 10 ans et je suis bien heureux de l'ouverture open source de la plateforme mais vérifier les dépendance est une bonne idée parce-que lors de la création d'un nouveau projet avec ASPNet core 6 incorporant l'identification individuelle, si vous prenez la peine de jeter soit un coup d'œil aux documents, soit aux package qui sont chargés lors de l'utilisation vous vous rendrez compte que les packages utilisés pour intégrer un serveur d'identification basé sur oauth ne sont plus ceux open source d'Identity serveur 4, mais ceux de Duende Server. Pour information Duende est une compagnie crée par les développeurs d'Identity Serveur, et la version suivante d'Identity serveur est publiée par cette entreprise sous une License Reciproque gratuite pour le développement et les tests, mais payante sur la production. voiçi l'extrait du pdf expliquant la licence

        By accessing the Duende™ IndentityServer software libraries, you are agreeing to one of the following licenses: • If you wish to evaluate or use the Duende™ software libraries in a NonCommercial Manner* , you may download and access the source and/or binaries at no charge under the Reciprocal Public License 1.5 (RPL-1.5) (the “RPL”); or • If you are a Small Entity** and wish to use the Duende™ software libraries commercially for one year, you may download and use them (without any payment) under the Software License Agreement below; or • If you wish to use the Duende™ software libraries commercially for one year, you may download and use them (with the appropriate payment) under the Software License Agreement below. *Non-Commercial Manner – consistent with the RPL – means any use of the Duende™ software libraries by: (i) an individual (and not a business entity) solely for their personal, private, and non-commercial purposes; or (ii) an individual or business entity in an experimental manner to understand its nature, limits, and potential uses. **Small Entity means that you are: (i) an individual, or a business entity that generates less than US$1M per year in gross revenues from all commercial activities (including all your affiliates); and (ii) the Duende™ software libraries will only be used to link and interoperate with five or fewer client software applications.

        Voici le PDF complet:

        Démonstration :

        PS D:\dotnet6> dotnet new angular --auth Individua
        Le modèle « ASP.NET Core with Angular » a bien été créé.
        
        
        Traitement des actions postérieures à la création en cours... Merci de patienter.
        Exécution de « dotnet restore » sur D:\perso\dotnet6\dotnet6.csproj...
          Identification des projets à restaurer...
          Restauration effectuée de D:\perso\dotnet6\dotnet6.csproj (en 673 ms).
        Restauration réussie.
        
        PS D:\dotnet6> dotnet buil
        Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 pour .NET
        Copyright (C) Microsoft Corporation. Tous droits réservés.
        
        
          Identification des projets à restaurer...
          Tous les projets sont à jour pour la restauration.
          dotnet6 -> D:\perso\dotnet6\bin\Debug\net6.0\dotnet6.dll
          v14.18.1
          Restoring dependencies using 'npm'. This may take several minutes...
        
        La génération a réussi.
            0 Avertissement(s)
            0 Erreur(s)
        
        
        Temps écoulé 00:00:28.12
        
        PS D:\perso\dotnet6> dotnet run
        info: Duende.IdentityServer.Startup[0]
              Starting Duende IdentityServer version 5.2.0+1c3f1fadb0fa7a4bea3f4a6f7028cbfcff3b9918 (.NET 6.0.0-rtm.21522.10)
        warn: Duende.IdentityServer[0]
           **   You do not have a valid license key for Duende IdentityServer. This is allowed for development and testing scenarios. If you are running in production you are required to have a licensed version. Please start a conversation with us: https://duendesoftware.com/contact
        info: Duende.IdentityServer.Startup[0]**__
              Using explicitly configured authentication scheme Identity.Application for IdentityServer
        info: Microsoft.Hosting.Lifetime[14]
              Now listening on: https://localhost:7101n
        

        Le message de warning est assez explicite.

        • [^] # Re: Publicité mensongère éhontée ?!!

          Posté par  . Évalué à -8.

          Oui c'est un changement récent.

          Ce n'est pas déconnant de vouloir vivre du fruit de son travail cependant.

          Heureument, il y'a d'autres fournisseurs du même service.

          Une chose similaire est arrivée avec la bibliothèque libre eeplus. Les devs en ont eu marre de travailler gratis.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Publicité mensongère éhontée ?!!

            Posté par  (site web personnel) . Évalué à 10.

            Ce n'est pas déconnant de vouloir vivre du fruit de son travail cependant.

            Je ne vois pas le rapport entre cette phrase et quitter le libre.

            Perso je vis de mon travail libre.

            Les devs en ont eu marre de travailler gratis

            Libre ne veut pas dire gratuit, certes difficile de vendre en libre 1000 fois le même travail mais il y a d'autres façons de vendre.

            De manière générale, ces phrases sont des insultes au libre, qui a montré depuis longtemps qu'on peut faire du business tout en faisant du libre.

            Pas de soucis pour qui veut quitter le libre, tout le monde est libre de changer d'avis et essayer autre chose, mais pas la peine de mentir, des personnes ont juste penser pouvoir gagner plus en faisant du non libre, que le meilleur gagne.

            • [^] # Re: Publicité mensongère éhontée ?!!

              Posté par  . Évalué à -2.

              J'ai pas dit que j'étais d'accord avec leurs justifications. ;-)

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # Coquilles

    Posté par  . Évalué à 6.

    Voici quelques coquilles de traduction. C'est fou, je l'ai relu plein de fois pourtant !

    ainsi que la prise en charge des la

    -> ainsi que la prise en charge de la

    La PGO dynamique aura des temps de démarrage légèrement plus lents que le runtime par défaut,

    -> La PGO dynamique aura des temps de démarrage légèrement plus importants que le runtime par défaut,

    C’est là où la magie a lieu.

    -> C'est ici que la magie opère.

    le type concret de source

    -> le type concret source

    si le type de source

    -> si le type source

    (et c’était possible).

    -> (lorsque cela était possible).

    profitent à tous les systèmes d’exploitation

    -> sont bénéfiques pour tous les systèmes d'exploitation

    Nous avons également identifié le besoin de fonctionnalités d’E/S sur les fichiers plus performantes :

    -> Nous avons également identifié le besoin de fonctionnalités d’E/S sur les fichiers plus performantes  pour les cas d'usage suivants :

    et de génération de code au moment de l’exécution

    -> et la génération de code au moment de l’exécution

    Veuillez commencer à migrer vos applications vers .NET 6, en particulier les applications .NET 5

    concepts propres MSBuild

    -> concepts propres à MSBuild

    Ainsi, les structures d’enregistrement sont une histoire naturelle de croissance pour les tuples.

    -> Ainsi, les structures d'enregistrement sont une évolution naturelle des Tuples.

    vous pouvez facilement déclarer l’enregistrement struct positionnel correspondant et t maintenir la sémantique mutable

    -> vous pouvez facilement déclarer la structure d'enregistrement positionnel correspondante et garder l'aspect mutable de la sémantique

    La bibliothèque centrale de F#

    -> La bibliothèque standard de F#

    et Arm32 avant cela.

    -> et Arm32 auparavant.

    les performances de l’Arm64 en général.

    -> les performances sur Arm64 en général.

    -> Veuillez commencer à migrer vos applications .NET vers .NET 6, en particulier les applications .NET 5

    Si vous tirez l’étiquette 6.0 de l’un de nos dépôts de conteneurs, vous tirerez une image Debian

    -> Si vous téléchargez l'un de nos conteneurs étiquetés en version 6.0 depuis l'un de nos dépôts, vous téléchargez une image Debian

    Credit to Michal Petryka.

    -> Merci à Michal Petryka.

    Merci à John Kelly, Huo Yaoyuan, and Robin Lindner.

    -> Merci à John Kelly, Huo Yaoyuan, et Robin Lindner.

    Ceci est utile si vous souhaitez prendre en charge une bibliothèque faisant partie d’une application à fichier unique.

    -> Ceci est utile pour les auteurs de bibliothèques qui veulent prendre en charge le cas des applications à fichier unique.

    Titre:

    Single-file debugging

    -> Déboguage d'applications à fichier unique

    Le découpage était jusqu’à présent uniquement disponible sous forme de préversion

    -> L'élagage était jusqu’à présent uniquement disponible sous forme de préversion

    n’était pas prête pour l’élagage pas (manque d’annotations par exemple).

    -> n’était pas prête pour l’élagage (manque d’annotations par exemple).

    sous-jacent le supporte.

    -> sous-jacent le prend en charge.

    les performances du traitement JSON

    -> les performances de traitement JSON

    lorsqu’ils sont des locaux, des arguments ou des valeurs de retour de méthodes).

    -> lorsqu'elles sont des variables locales, des arguments ou des valeurs de retour de méthodes.

    (sans nécessiter ou démarrer le runtime).

    -> (sans nécessiter de démarrer le runtime).

    Si un modo pouvait passer les corriger, svp ?

    Merci ! Et désolé pour toutes ces fautes ! :/

    "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Coquilles

      Posté par  . Évalué à 3.

      dans votre installation kit de développement

      dans votre installation du kit de développement.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # Imbuvable et n'a rien à faire ici

    Posté par  . Évalué à -2. Dernière modification le 26 décembre 2021 à 19:31.

    Qu'est-ce que c'est que ce charabia ? Du début à la fin on a l'impression de lire une traduction automatique ratée, d'un texte original qui tient plus du marketing que de la technique (combien de fois l'expression "hautes performances" dans le texte ?)

    Sérieux, ça sur linuxfr ? Misère…

    • [^] # Re: Imbuvable et n'a rien à faire ici

      Posté par  . Évalué à 2.

      une traduction automatique ratée

      C'est simplement quand on essaye de franciser l'informatique pour faire plaisir aux Toubonistes. Ça sonne faux.

      • [^] # Re: Imbuvable et n'a rien à faire ici

        Posté par  . Évalué à -5.

        Qu'est-ce que la loi Toubon vient faire ici ? J'étais plutôt gentil avec l'idée que ce serait une traduction ratée, il est clair que le texte d'origine en anglais n'est que du blabla marketoïde en mode auto-satisfaction.

        N'importe quel informaticien grince des dents à presque chacune des phrases de ce communiqué commercial qui essaye (vainement) de faire croire qu'il a un contenu technique pertinent.

        Comment un déchet pareil a pu trouver sa voie sur linuxfr ?

        • [^] # Re: Imbuvable et n'a rien à faire ici

          Posté par  . Évalué à 10. Dernière modification le 26 décembre 2021 à 21:29.

          Bah c'est simple:

          1. Tu vas dans l'onglet 'Rédaction'
          2. Tu demandes et obtiens de la part de l'auteur la permission de traduire.
          3. Tu traduis
          4. Tu révises des centaines de fois ton texte.
          5. Tu envoie ça à la modération
          6. Tu déclenche les trolls et tu profite ! :D

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Imbuvable et n'a rien à faire ici

            Posté par  . Évalué à -9. Dernière modification le 27 décembre 2021 à 01:04.

            C'est le texte d'origine qui pose problème. Et que ta traduction ait pu passer le processus de sélection de LinuxFR pose un ÉNORME problème.

            • [^] # Re: Imbuvable et n'a rien à faire ici

              Posté par  . Évalué à 10.

              Pour lutter contre l'ÉNORME problème d'avoir du contenu technique sur linuxfr, je propose de demander massivement le remboursement de nos abonnements.

              Ce geste militant va forcément faire réagir les actionnaires

    • [^] # Re: Imbuvable et n'a rien à faire ici

      Posté par  . Évalué à 0.

      Bah ouuais mon gars, mais c'est l'avenir !

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Imbuvable et n'a rien à faire ici

      Posté par  . Évalué à 0.

      "hautes performances"

      Je serais curieux de savoir par quoi tu l'aurais traduit. C'est pourtant pas compliqué comme concept.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: Imbuvable et n'a rien à faire ici

        Posté par  . Évalué à 2.

        C'est de le répéter à longueur de phrases sur des questions des plus banales qui confine au ridicule (et tout le reste est à l'avenant).

        • [^] # Re: Imbuvable et n'a rien à faire ici

          Posté par  . Évalué à 1.

          Bah c'est le problème de la traduction alors. C'est le texte très exactement traduit. Va lire l'original, ce sera le même texte - avec encore moins d'explications (car ce n'est pas le même public).

          Peux tu proposer ta propre traduction dans ce cas ?

          et tout le reste est à l'avenant.

          Mais encore ?

          C'est pas très argumenté tout ça. Mon idée est que tu troll.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Imbuvable et n'a rien à faire ici

            Posté par  . Évalué à -3.

            Si trollesque il y a, c'est d'avoir réussi à passer un article aussi creux techniquement, que risible au niveau du langage marketoïde et faisant en plus de la publicité grossière à Microsoft, sur… Linuxfr.

            • [^] # Re: Imbuvable et n'a rien à faire ici

              Posté par  . Évalué à 5.

              J'ai rien vu de creux techniquement, au contraire y'a du très concret. Rien que le JIT et l'AOT par exemple. Le R2R, les reproductibles builds…

              Mais ça passe au dessus de la tête des trolls.

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: Imbuvable et n'a rien à faire ici

                Posté par  . Évalué à -10.

                Ne fais pas semblant d'être un lecteur, "xcomcmdr" tu es l'auteur de cette horreur. C'est pathétique de faire mine du contraire.

                NOTE: il n'y a vraiment plus de modération à linuxfr pour laisser passer de tels ramassis de sottises (article et commentaires de "xcomcmdr" ?)

                • [^] # Re: Imbuvable et n'a rien à faire ici

                  Posté par  . Évalué à 8.

                  J'attends toujours tes arguments au lieu d'attaques personnelles.

                  En tant qu'auteur, je l'ai relu et étendu plein de fois.

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                  • [^] # Re: Imbuvable et n'a rien à faire ici

                    Posté par  . Évalué à -10.

                    "attaque personnelle" ? Tu fais mine d'être un lecteur de ton propre article et le défendre comme un tiers ! C'est une question d'honnêteté intellectuelle de base.

                    Tu as "étendu" une traduction ? Comment un tel prodige est-t-il possible ?

                    Tu es un troll pro-MS, qui ne maîtrise pas vraiment le sujet et qui a traduit servilement un communiqué marketing de Microsoft déjà caricatural. Je n'arrive pas à comprendre comment un truc pareil a pu passer la modération.

                    • [^] # Re: Imbuvable et n'a rien à faire ici

                      Posté par  . Évalué à 2. Dernière modification le 27 décembre 2021 à 07:56.

                      XD

                      Je m'étrangle de rire. Merci !

                      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                    • [^] # Re: Imbuvable et n'a rien à faire ici

                      Posté par  . Évalué à -2. Dernière modification le 03 janvier 2022 à 01:48.

                      Toi en fait avec ta haine de Microsoft tu as…5 ans ?

                      C'est tellement gamin comme comportement, c'est triste a voir.

  • # Hé ho la modération ?

    Posté par  . Évalué à -7.

    Comment pouvez-vous laissez passer une traduction foutraque (le traducteur ne maîtrise clairement ni la langue française, ni l'informatique) d'un article d'origine "corporate" Microsoft dont le contenu technique est parfaitement ridicule (ils s'y vantent d'avoir corrigé les bugs qu'ils ont eux-même introduit ou présentent des banalités comme l'innovation du siècle) et a été pondu par le département de communication de Microsoft ???!!!

    • [^] # Re: Hé ho la modération ?

      Posté par  . Évalué à 5.

      💖 Change pas linuxfr.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Hé ho la modération ?

      Posté par  (site web personnel) . Évalué à 10.

      J'interviens en tant que modérateur, puisque nous sommes sollicités, mais je trouve que xcomcmdr gère très bien les commentaires de cette dépêche.

      On a donc une dépêche :
      - sur un sujet technique,
      - en rapport avec le libre,
      - qui est une traduction sous licence libre (merci à l'auteur du post original),
      - et réalisée par un contributeur de longue date.

      Je ne vois pas pourquoi nous l'aurions refusée. Parce qu'il s'agit de Microsoft ? Heureusement la question du libre dépasse le créateur du logiciel, du coup tant que le sujet rentre dans les cases, ça passe. Le site LinuxFr.org n'a pas de vocation militante.

      J'ai fait le tour de tes contributions et je ne peux que t'encourager à participer plus, notamment aux dépêches et aux journaux, afin de mieux te familiariser avec les thèmes du site. Un peu comme l'auteur de cette dépêche par exemple ;)

      • [^] # Re: Hé ho la modération ?

        Posté par  . Évalué à -8.

        Il y a une impérieuse nécessité à ne pas relayer la propagande Microsoft.

        Car le sujet principal est la liberté. Si aujourd'hui Microsoft est obligé de faire un peu d'open source, c'est parce que des gens ont mené combat, pour la liberté. Si on avait laisser faire Microsoft, il n'y aurait plus moyen d'écrire une boucle dans un programme sans leur autorisation ou sans leur payer des droits. Les menaces continuent !

        Quand Microsoft s'en prend à nos données de santé ou passe des contrats pour envahir nos écoles ou fait du libre-washing ou continue d'enfermer logiciellement des centaines de millions d'utilisateurs ou continue d'abuser de monopole artificiels déloyaux, peut-on rester indifférent ? LinuxFR peut-il rester indifférent ?

        La puissance financière des GAFAM créé un déséquilibre monumentale avec le reste du monde. Il est urgent d'arrêter de le soutenir et pire, de le faire passer pour acceptable auprès des lecteurs de LinuxFR.

        Ne pas avoir conscience de ça, c'est passer à côté de tout et mettre en danger la liberté.

        Les règles de modération de LinuxFR prévoient que « LinuxFr.org ne doit pas servir à des gens (particuliers ou sociétés) comme plate‑forme publicitaire. » N'est-il pas envisageable de considérer cet article comme étant plus publicitaire que libriste ?

        • [^] # Re: Hé ho la modération ?

          Posté par  . Évalué à 9. Dernière modification le 28 décembre 2021 à 08:39.

          Les règles de modération de LinuxFR prévoient que « LinuxFr.org ne doit pas servir à des gens (particuliers ou sociétés) comme plate‑forme publicitaire. » N'est-il pas envisageable de considérer cet article comme étant plus publicitaire que libriste ?

          Une publicité te vend quelque chose avec un message centré sur le marketing.

          Ici, dotnet est non seulement gratuit, mais libre. Et au lieu d'un message marketing vide de sens juste pour s'arttaquer à ton portefeuille, tu as à la place un billet de blog très technique et très long à l'image des dépêches sur le kernel Linux.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: Hé ho la modération ?

            Posté par  . Évalué à 0.

            Ici, le produit c'est Microsoft qui veut se refaire une image et endormir les consciences pendant qu'il continue à enfermer les utilisateurs avec ses autres produits. Son nom est mentionné 32 fois !

            Stop au libre-washing sur LinuxFR !!!

            • [^] # Re: Hé ho la modération ?

              Posté par  . Évalué à 6.

              Ici, le produit c'est Microsoft qui veut se refaire une image et endormir les consciences pendant qu'il continue à enfermer les utilisateurs avec ses autres produits.

              [ref nécessaire] je vois surtout qu'ils ont compris que le développement d'un langage libre est plus intéressant. Je ne vois pas le rapport avec les autres produits.

              Son nom est mentionné 32 fois !

              C'est le développeur principal du produit. C'est la même chose quand une dépêche Firefox parle de Mozilla.

              « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

              • [^] # Re: Hé ho la modération ?

                Posté par  (site web personnel, Mastodon) . Évalué à 4.

                Je suis en train de parcourir de nouveau les dépêches sur Firefox. Pour l'instant, je n'en trouve pas où on martèle Mozilla 32 fois…

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

                • [^] # Re: Hé ho la modération ?

                  Posté par  . Évalué à 6.

                  En même temps, Firefox n'intéresse personne au point de faire des dépêches aussi longue.

                  « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                  • [^] # Re: Hé ho la modération ?

                    Posté par  (site web personnel) . Évalué à 0.

                    Pas faux si on comprend bien le mot « intéresse » dans un sens de bénéfices en termes de verrouillage des marchés, de domination sur la concurrence… Firefox n'a pas vocation à enchaîner le monde. Si j'ai bonne mémoire le but initial était plutôt dans l'offre d'une alternative sérieuse à un produit sérieusement vérolé et verrouillant.

                    « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

        • [^] # Re: Hé ho la modération ?

          Posté par  (site web personnel) . Évalué à 3.

          Car le sujet principal est la liberté

          Tu as sans doute raté un truc, alors pour information le sujet principal est les 4 libertés définies du libre par la FSF (la prose autour des 4 libertés est du marketing pour qui aime le marketing mais ne fait pas partie de la définition), quasiment synonyme des libertés du libre définies par Debian et OSI.

          Est-ce que cette dépêche respecte ça? Oui, explicitement.

          Pour autre information, le libre interdit d'empêcher une entité qu'on n'aime pas, et ici tu voudrais empêcher une entité parce que tu la juges dangereuse (à la Minority Report en plus). Le plus hors sujet dans le sujet (le libre et ses libertés) c'est toi.

          Ce que tu n'as peut-être pas compris dans la liberté du libre est que le libre est la pour protéger les utilisateurs de toi et ta vison, plutôt que de Microsoft avec son .net 100% libre. Merci à lui de nous protéger de la sorte, perso c'est bien pour ça que j'aime le libre.

          • [^] # Re: Hé ho la modération ?

            Posté par  . Évalué à -5.

            la prose autour des 4 libertés est du marketing

            Sauf que ce que tu décris, c'est l'open source, pas le Libre. Historiquement et philosophiquement, l'éthique a toujours fait partie du mouvement du Libre.

            L'open source as ta préférence, c'est ton choix mais merci de ne pas dévoyer le vrai sens du Libre.

            Est-ce que cette dépêche respecte ça? Oui, explicitement.

            NON. Un texte de propagande sous licence libre n'en reste pas moins un texte de propagande.

            Tu fais le choix d'ignorer cet aspect et d'être aveugle aux dangers des GAFAM.

            • [^] # Re: Hé ho la modération ?

              Posté par  . Évalué à 5.

              La license MIT est 100% compatible GPL.

              Le Libre, c'est l'arbitraire alors ?

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: Hé ho la modération ?

                Posté par  . Évalué à -4.

                Justement, le choix de la licence MIT n'est pas du tout anodin de la part du GAFAM. Ça lui permet dans le futur de faire du logiciel privateur à partir de ce code open source, de le transformer en boites noires pour mieux enfermer les utilisateurs. Le procédé est connu et abjecte. Les utilisateurs méritent de meilleures garanties de liberté, éthiques et loyales.

                • [^] # Re: Hé ho la modération ?

                  Posté par  . Évalué à 4.

                  Ah, encore du FUD.

                  Une licence plus permissive que la GPL est pas libre. OK.

                  Admettons… Que fais tu de tous les forks/clones des repots contenant le sdk et du fait que git est distribué ? MS peut les faire disparaître d'un coup ?

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                • [^] # Re: Hé ho la modération ?

                  Posté par  (site web personnel) . Évalué à 3. Dernière modification le 31 décembre 2021 à 07:26.

                  D'une on parlait de libre et maintenant tu parles d'autre chose, perso je prend comme le fait que tu as compris que tout est libre donc.

                  De deux ça serait GPL que ce serait exactement pareil dans les possibilités dont tu parles. Si si… RMS n'ayant pas pris la peine d'interdire à l'ayant-droit de fermer le code dont il a les droits, rien ne l'en empêche (le libre façon GPL est super pour faire du business non libre, voir par exemple MySql).

                  Comprends-tu ce qu'est le libre? Tu devrais xommencer par te renseigner dessus avant de cracher sur ceux qui en font (Microsoft mais aussi moi en pratique).
                  Ici, on voit surtout un Microsoft qui apporte une pierre au libre et un cpm qui n'apporte rien au libre (elle est ou ta contribution au libre?), Microsoft fait bien plus pour le libre que cpm.

                  Rien de nouveau, beaucoup de gens pensent aimer quelque chose qu'ils n'ont pas compris, ils pensent que le libre s'intéresse à l'auteur ou à une communauté alors que le libre ne s'intéresse qu'à la liberté de celui qui reçoit et ça fait des quiproquos (faut dire que la couche marketing de la FSF n'aide pas… mais ça ne change rien dans les 4 libertés du libre qu'elle a défini, la seule chose commune à tous les acteurs du libre).

                  Au final, la seule chose qu'on comprend et que tu n'aimes pas tant que ça les libertés du libre, elles laissent trop de libertés aux gens à ton goût. Perso c'est bien parce que le libre (tel que défini par la FSF) me protège de ta volonté de limiter sous fausse excuse de protéger que je l'aime.

            • [^] # Re: Hé ho la modération ?

              Posté par  (site web personnel, Mastodon) . Évalué à 10.

              Tu sais quoi ? Tu fais ce qui t'a été suggéré, à savoir, prendre ton plus beau (ou le plus moche, c'est selon) clavier pour allumer un contrefeu et noyer cette odieuse dépêche sous une avalanche de dépêches sur des sujets qui te semblent plus compatibles avec ta notion du logiciel libre. Y'a pas plus efficace.

              Si tu manques d'idées, quelques-unes piquées dans les liens du site :

              Tu peux aussi faire un tutoriel avec ton logiciel libre favori ou donner tes astuces sur un langage que tu utilises, voire, nous pondre une doctrine sur les mérites comparés des différentes licences, etc.

              Ce ne sont pas les sujets qui manquent.

              On se régale à l'avance des dépêches que tu vas nous soumettre et qui, compte tenu de l'exigence que tu manifestes ici, ne manqueront pas, je n'en doute pas une milli-seconde, d'être tout à la fois, intelligentes, pertinentes, utiles et agréables à lire et sans la moindre trace de Gafam.

              Mais sinon, on a bien compris ta position, merci.

              « Tak ne veut pas quʼon pense à lui, il veut quʼon pense », Terry Pratchett, Déraillé.

        • [^] # Re: Hé ho la modération ?

          Posté par  . Évalué à -4. Dernière modification le 03 janvier 2022 à 01:50.

          Moi je t'invite à grandir, passer la puberté et arrêter de nous faire une crise parce qu'il y a Microsoft dans la dépêche. Ton comportement fait vraiment gamin de 5 ans.

  • # je m'en étrangle

    Posté par  . Évalué à -10. Dernière modification le 27 décembre 2021 à 02:08.

    '''

    Il s’agit d’une nouvelle version importante de .NET, avec des améliorations presque équivalentes en termes de performances, de fonctionnalités, de convivialité et de sécurité. Nous espérons que vous trouverez de nombreuses améliorations qui vous rendront plus efficace et plus compétent dans votre développement quotidien et qui augmenteront les performances ou réduiront les coûts de vos applications en production. Nous avons déjà commencé à recevoir de bons retours de la part de ceux d’entre vous qui ont déjà commencé à utiliser .NET 6.

    '''

    ah ouais quand même ! Et on est sur linuxfr ! Quelqu'un peut m'expliquer comment un paragraphe pareillement grotesque se trouve publié ICI ?

    • [^] # Re: je m'en étrangle

      Posté par  (site web personnel) . Évalué à 5.

      On dirait que Microsoft tente d'inonder LinuxFr de nouvelles plus ou moins interressantes
      Dans le but afin de noyer dans l'oeuf toutes les autres informations interressantes.

      technique éprouvée dans le CLUF de Microsoft

      Ou alors c'est une tentative désépéré de nous faire mourir d'ennui … :)

      D'abord ils vous ignorent, ensuite ils vous raillent, ensuite ils vous combattent et enfin, vous gagnez.

  • # Pas assez libre mon fils

    Posté par  (site web personnel) . Évalué à 10.

    Je suis content de voir que .NET est toujours vivant.

    Dommage que Microsoft est préféré faire un obscur clone de Java plutôt que d'y contribuer, mais au moins cela leur permets de garder le contrôle absolu.

    Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

    • [^] # Re: Pas assez libre mon fils

      Posté par  . Évalué à 0. Dernière modification le 27 décembre 2021 à 09:44.

      Si tu veux je fais une dépêche sur les évolutions de C# sur 20 ans et des comparaisons avec Java, si ça t'intéresse. ;-)

      Bah suite au procès avec Sun Microsystems, à l'époque y'avait pas le choix. Microsoft adorait Java et en mettait partout (on a même retrouvé LOG4J version 1.X au sein de MS SQL Server), et .NET Core n'a que 7 ans tandais que .NET Framework 1.1 (la toute première version) date de … 2003.

      Il a fallu attendre un véritable changement de culture en interne (l'arrivée d'ingénieurs pour lesquels le libre est une évidence) avant que ça bouge chez MS.

      Perso je suis ravi de voir enfin une techno qui s'inspire fortement de Java en retirer enfin les bénéfices qui aurait dû être gardés dès le début -> être multiplateforme.

      Ceci dit, il y a des contributions à Java:
      https://devblogs.microsoft.com/java/microsoft-deepens-its-investments-in-java/

      Même Visual Studio de nos jours sait reconnaître du Java (si, si !). Bon, il me semble que ce n'est que pour les projets ciblant Android, mais ça n'a pas fini de me surprendre.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: Pas assez libre mon fils

        Posté par  . Évalué à 7.

        Perso je suis ravi de voir enfin une techno qui s'inspire fortement de Java en retirer enfin les bénéfices qui aurait dû être gardés dès le début -> être multiplateforme.

        Ce n'est vraiment pas du troll, je ne suis pas d'assez prêt .Net pour être au courant. Il n'y a plus de petite astérisques là-dessus ? Genre WPF ou autre partie du SDK qui sont très couplés à Windows ?

        https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

        • [^] # Re: Pas assez libre mon fils

          Posté par  . Évalué à 4. Dernière modification le 28 décembre 2021 à 16:09.

          La base est multiplateforme.

          Si tu te mets à importer winforms ou wpf dans ton projet (chose à faire explicitement) tu vas te lier à Windows, vu que l'un ou l'autre ont des dépendances natives Windows.

          Si tu veux une alternative multiplateforme à wpf/winforms tout en utilisant toujours dotnet, il y a par exemple AvaloniaUI.

          Évidement il est recommandé de garder un code multiplateforme.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # MONO ?

    Posté par  . Évalué à 3.

    Quant est-il de MONO ?
    Vont-ils fusionner ?
    Y a-t-il encore une utilité ?
    Se servent-ils des sources maintenant ouverte de .Net ?

    • [^] # Re: MONO ?

      Posté par  . Évalué à 5.

      La fusion est faite.

      À part pour des cas à la marge (mais alors au point que j'ai peine à imaginer lesquels), il n'y a plus besoin de Mono.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: MONO ?

        Posté par  . Évalué à 2.

        Merci de ta réponse.
        Donc que l'on utilise MONO ou .net c'est pareil ? Ou le .net utilise t'il toujours du code non libre ?

        • [^] # Re: MONO ?

          Posté par  . Évalué à 3. Dernière modification le 04 janvier 2022 à 17:54.

          Mono c'est son propre SDK et CLR, donc faut le faire exprès pour l'utiliser. Ça existe toujours, mais ce n'est pas le choix par défaut.

          Le choix par défaut c'est .NET 5 ou ultérieur, qui est libre et gratuit depuis toujours, et tourne sur autant de plateformes que Mono (c'est à dire Linux, Mac, et Windows).

          Et n'est plus juste un port minimaliste du SDK + CLR du .NET Framework comme au temps de .NET Core 1.X/2.X.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # PGO

    Posté par  . Évalué à 6.

    Je suis surpris pour le PGO je pensais que c'était le cas depuis longtemps. Si j'ai bien compris c'est ce qu'on trouve sur java depuis… 22 ans (j'ai dû chercher).

    Comment ça fonctionnait ? En java la compilation est séparée en 2 parties C1 et C2.

    • C1 est une compilation de java vers le bytecode de la jvm. C'est exécuté par le développeur (c'est le bytecode qui est livré)
    • C2 se déclenche après le début de l'exécution du programme. Après avoir eu suffisamment de stats venant de l'interprétation du bytecode, hotspot choisi ce qu'il va compiler (en natif) et comment. Il peut ensuite revenir sur ses choix de compilation pour recompiler autrement. C'est l'étape d'interprétation du bytecode qu'on appel la chauffe de la jvm.

    Si j'ai bien compris pour C# c'est au démarrage que tu as une compilation native ? Et maintenant il peut choisir de recompiler autrement des parties en fonction d'informations qu'il aura collecté à l’exécution ?

    https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: PGO

      Posté par  . Évalué à 4. Dernière modification le 28 décembre 2021 à 15:28.

      Profil Guided Optimization (PGO) et JIT (compilation Just In Time) ne sont pas la même chose.

      Basé sur un profil, ça veut dire que ça se base sur les exécutions précédentes du programme. Il y a des patterns d'exécution qui sont les mêmes d'une exécution à une autre, donc autant optimiser ces parties-là. Surtout pour des programmes batch.

      En tout cas c'est comme ça que je le comprends.

      Pour WSL (Windows Subsystem for Linux), du PGO est aussi à l'ordre du jour pour le kernel Linux. On verra donc peut-être ça débarquer dans certaines distribs Linux classiques :-) (c'est drôle pcq Microsoft emploie des développeurs pour Linux et la GNU toolchain, chose inimaginable il y a une décennie).

      • [^] # Re: PGO

        Posté par  . Évalué à 4.

        Basé sur un profil, ça veut dire que ça se base sur les exécutions précédentes du programme. Il y a des patterns d'exécution qui sont les mêmes d'une exécution à une autre, donc autant optimiser ces parties-là. Surtout pour des programmes batch.

        De ce que je comprends il faut comprendre profil comme dans profiling. La page wikipedia anglaise de PGO semble expliquer que c'est bien ce que fait hotspot.

        Si je comprends bien. Le fait de le faire dynamiquement c'est ce que font hotspot et maintenant le .Net6 en pouvant revenir en arrière sur la compilation. Et tu peut le faire statiquement avec des compilateurs plus classiques si tu leur fournir une trace du profile (tu peux aussi le faire avec grallvm native image d'ailleurs).

        Pour WSL (Windows Subsystem for Linux), du PGO est aussi à l'ordre du jour pour le kernel Linux. On verra donc peut-être ça débarquer dans certaines distribs Linux classiques :-)

        Hum je comprends l'intérêt pour WSL ils doivent vouloir améliorer les performance et ont un usage un peu particulier de linux donc le binaire doit pouvoir être simplifié. Autant pour des distributions linux je vois pas.

        https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

    • [^] # Re: PGO

      Posté par  . Évalué à 3.

      Si j'ai bien compris pour C# c'est au démarrage que tu as une compilation native ?

      Si je me souviens bien, c'est à l'installation (sur la plateforme finale) qu'a lieu la compilation native (il me semble que c'était la raison des longues mises à jour .net sous windows xp).

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: PGO

      Posté par  . Évalué à 3.

      Je suis surpris pour le PGO je pensais que c'était le cas depuis longtemps. Si j'ai bien compris c'est ce qu'on trouve sur java depuis… 22 ans (j'ai dû chercher).

      Et encore, y'a même pas d'AOT. Alors que ça existe déjà en Java depuis 2019 au moins.

      Quant au PGO, il est encore facultatif. Il est intéressant pour les applications qui s'exécutent longtemps (comme une application Web). Il optimise le code selon son usage à l'exécution.

      Comment ça fonctionnait ? En java la compilation est séparée en 2 parties C1 et C2.

      C'est pareil, sauf que ça s'appelle l'IL (ou MSIL) pour Intermediate Language.

      Ensuite, le code executé (et non pas toute l'application en une seule fois) est JITé.

      Le résultat de la compilation JIT est gardé en mémoire.

      Traditionnellement à la place de la PGO et de l'AOT, C# expose plus d'APIs et de types bas niveau pour pouvoir optimiser le code utilisateur ainsi que code de la bibliothèque standard (comme Span qui est super rapide, le mot clé ref, stackalloc, …).

      Ici, il est clair que dotnet est en train de jouer à rattraper le train côté optimisation de la VM.

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: PGO

        Posté par  (site web personnel) . Évalué à 6.

        Ici, il est clair que dotnet est en train de jouer à rattraper le train côté optimisation de la VM.

        Juste à temps pour l'abandon du concept de VM au profit de la compilation native :-)

        Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

        • [^] # Re: PGO

          Posté par  . Évalué à 2.

          Oui j'ai hâte de voir ça.

          Je sais que CoreRT était déjà utilisé par Street of Rage 4 et d'autres produits, mais perso j'aimerais que la réflexion ne pose pas autant de problème pour la compilation native… Y'a des bibliothèques qui en utilisent partout, et tout le monde ne va pas passer aux générateurs de sources…

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

  • # Commentaire supprimé

    Posté par  . Évalué à 10.

    Ce commentaire a été supprimé par l’équipe de modération.

  • # Manque de contexte autour de l'article

    Posté par  (site web personnel) . Évalué à 1.

    J'arrive après la bataille, mais j'avais envie de réagir concernant cette traduction de ce long article.
    C'est très intéressant d'avoir des infos sur le libre, même celui fourni par Microsoft. J'ai commencé à lire cette dépêche sans à priori. Mais honnêtement j'ai été soûlé après 10% de lecture, à cause du ton que je trouve trop commercial (trop US à mon goût ?) .
    J'aimerais savoir :
    - Si l'article original a été écrit par un salarié de Microsoft dans le cadre de son travail
    - Si Xcomcmdr est un salarié de Microsoft qui a assuré la traduction de l'article et les réponses aux commentaires dans le cadre de son travail également.
    Si c'est le cas, j'aurais préféré que ces 2 points et le fait que se soit une traduction apparaissent clairement en préambule de l'article, comme il me semble qu'il est d'usage sur DLFP (cf les traductions des newsletter XMPP). Ça n'enlève rien à la valeur du travail réalisé et ça n'aurait peut-être pas empêché les humeurs trollesques, mais ça aurait resitué cette dépêche dans son contexte.

    • [^] # Re: Manque de contexte autour de l'article

      Posté par  . Évalué à 2.

      1. Oui
      2. Non
      3. J'ai rajouté plus de contexte (explications, beaucoup de liens en plus), mais c'est difficile sans sortir du cadre de la traduction sous licence.

      J'ai appris la leçon et si y'a une prochaine fois une autre approche que la traduction s'impose.

      Le texte original posait encore moins le contexte (pour PowerShell, le filtrage par motif, …).

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.