IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Dotnet Discussion :

.NET : la version 7 du framework de développement d'applications serait la plus rapide de tous les temps


Sujet :

Dotnet

  1. #1
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    mai 2019
    Messages
    1 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Rédacteur technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : mai 2019
    Messages : 1 016
    Points : 20 660
    Points
    20 660
    Par défaut .NET : la version 7 du framework de développement d'applications serait la plus rapide de tous les temps
    Microsoft annonce .NET 7 Preview 6, la version du framework pour la création des applications,
    améliore les convertisseurs de type, personnalise des contrats JSON

    Microsoft a annoncé en début d’année la disponibilité de la Preview 1 de .NET 7. Le 12 juillet, Jon Douglas, Directeur de programme senior, NuGet, annonce la sortie de .NET 7 Preview 6. « Aujourd'hui, nous avons publié la Preview 6 de .NET 7. Cette Preview de .NET 7 comprend des améliorations des convertisseurs de type, la personnalisation des contrats JSON, des mises à jour de l'API System.Formats.Tar, des contraintes pour la création de modèles .NET et des améliorations des performances dans le domaine de CodeGen », déclare Jeremy Likness, Directeur de programme principal chez Microsoft.


    « .NET 7 s'appuie sur la base établie par .NET 6, qui comprend un ensemble unifié de bibliothèques de base, de runtime et de SDK, une expérience de développement simplifiée et une productivité accrue des développeurs. Les principaux domaines d'intérêt de .NET 7 comprennent une meilleure prise en en charge des scénarios cloud native, des outils facilitant la mise à niveau des projets existants et la simplification de l'expérience du développeur en facilitant le travail avec les conteneurs », a écrit Jeremy Likness de l'équipe .NET à propos de cette version. En gros, .NET 7 vise à faciliter le développement d'applications cloud natives et la conteneurisation.

    Nom : donet.png
Affichages : 26940
Taille : 1,3 Ko

    .NET 7 Preview 6 a été testé avec Visual Studio 17.3 Preview 3. Il est recommandé d'utiliser les builds du canal Preview ppour l’essai de .NET 7 avec les produits de la famille Visual Studio. Sous macOS, il est recommandé d'utiliser la dernière version de Visual Studio 2022 pour Mac. Voici, ci-dessous, les nouvelles fonctionnalités qu’apporte la Preview 6 de .NET 7.

    Convertisseurs de type

    Il existe maintenant des convertisseurs de type exposés pour les nouveaux types primitifs DateOnly, TimeOnly, Int128, UInt128 et Half.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    namespace System.ComponentModel
    {
        public class DateOnlyConverter : System.ComponentModel.TypeConverter
        {
            public DateOnlyConverter() { }
        }
        public class TimeOnlyConverter : System.ComponentModel.TypeConverter
        {
            public TimeOnlyConverter() { }
        }
     
        public class Int128Converter : System.ComponentModel.BaseNumberConverter
        {
            public Int128Converter() { }
        }
     
        public class UInt128Converter : System.ComponentModel.BaseNumberConverter
        {
            public UInt128Converter() { }
        }
     
        public class HalfConverter : System.ComponentModel.BaseNumberConverter
        {
            public HalfConverter() { }
        }
    }

    Personnalisation du contrat JSON

    Dans certaines situations, les développeurs qui sérialisent ou désérialisent JSON constatent qu'ils ne veulent pas ou ne peuvent pas changer les types, soit parce qu'ils proviennent d'une bibliothèque externe, soit parce que cela polluerait grandement le code, mais qu'ils ont besoin d'effectuer certains changements qui influencent la sérialisation, comme la suppression d'une propriété, la modification de la façon dont les nombres sont sérialisés, la façon dont les objets sont créés, etc. Ils sont souvent obligés d'écrire des wrappers ou des convertisseurs personnalisés, ce qui est non seulement fastidieux mais rend également la sérialisation plus lente.

    La personnalisation du contrat JSON permet à l'utilisateur d'avoir un meilleur contrôle sur les types qui sont sérialisés ou désérialisés et sur la manière dont ils le sont.

    Se lancer dans la personnalisation

    Il y a deux façons de base pour les développeurs de « se brancher » sur la personnalisation, elles aboutissent toutes deux à l'attribution de JsonSerializerOptions.TypeInfoResolver et nécessitent l'attribution de resolver :

    • Le développeur peut utiliser DefaultJsonTypeInfoResolver et ajouter son modificateur, tous les modificateurs seront appelés en série :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      JsonSerializerOptions options = new()
      {
          TypeInfoResolver = new DefaultJsonTypeInfoResolver()
          {
              Modifiers =
              {
                  (JsonTypeInfo jsonTypeInfo) =>
                  {
                      // your modifications here, i.e.:
                      if (jsonTypeInfo.Type == typeof(int))
                      {
                          jsonTypeInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString;
                      }
                  }
              }
          }
      };
       
      Point point = JsonSerializer.Deserialize<Point>(@"{""X"":""12"",""Y"":""3""}", options);
      Console.WriteLine($"({point.X},{point.Y})"); // (12,3)
       
      public class Point
      {
          public int X { get; set; }
          public int Y { get; set; }
      }
    • Écrire son propre résolveur personnalisé en implémentant ;
    • System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver ;
    • Lorsque le type n'est pas géré, le code doit retourner null ;
    • IJsonTypeInfoResolver peut être combiné avec d'autres pour former un résolveur efficace qui retournera la première réponse non nulle. Par exemple, JsonTypeInfoResolver.Combine(new MyResolver(), new DefaultJsonTypeInfoResolver()).

    Personnalisations

    La fonctionde IJsonTypeInfoResolver est de fournir JsonTypeInfo pour toute demande de sérialiseur de type, cela ne se produira qu'une fois par type et par option. JsonTypeInfo.Kind déterminera quels boutons le développeur peut changer et est déterminé en fonction du convertisseur qui est déterminé en fonction des convertisseurs fournis aux options. Par exemple, JsonTypeInfoKind.Object signifie que des propriétés peuvent être ajoutées/modifiées tandis que JsonTypeInfoKind.None signifie qu'aucun des boutons n'est garanti d'être utilisé cela peut arriver quand le type a un convertisseur personnalisé.

    JsonTypeInfo est soit créé par DefaultJsonTypeInfoResolver avec des boutons pré-remplis provenant par exemple d'attributs personnalisés, soit peut être créé de toutes pièces par l'utilisateur : JsonTypeInfo.CreateJsonTypeInfo, la création à partir de zéro signifie que l'utilisateur devra également définir JsonTypeInfo.CreateObject.

    Personnalisation des propriétés

    Les propriétés ne sont pertinentes que lorsque JsonTypeInfo.Kind == JsonTypeInfoKind.Object et, dans le cas de DefaultJsonTypeInfoResolver, elles seront préremplies. Elles peuvent être modifiées ou créées à l'aide de JsonTypeInfo.CreateJsonPropertyInfo et ajoutées à la liste des propriétés, par exemple, si vous obtenez une classe d'une autre bibliothèque dont les API sont bizarrement conçues et que vous ne pouvez pas les modifier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MyClass
    {
        private string _name = string.Empty;
        public string LastName { get; set; }
     
        public string GetName() => _name;
        public void SetName(string name)
        {
            _name = name;
        }
    }

    Avant que cette fonctionnalité n'existe, il faut créer son propre convertisseur personnalisé pour ce type.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    JsonSerializerOptions options = new()
    {
        TypeInfoResolver = new DefaultJsonTypeInfoResolver()
        {
            Modifiers = { ModifyTypeInfo }
        }
    };
     
    MyClass obj = new()
    {
        LastName = "Doe"
    };
     
    obj.SetName("John");
     
    string serialized = JsonSerializer.Serialize(obj, options); // {"LastName":"Doe","Name":"John"}
     
    static void ModifyTypeInfo(JsonTypeInfo ti)
    {
        if (ti.Type != typeof(MyClass))
            return;
     
        JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), "Name");
        property.Get = (obj) =>
        {
            MyClass myClass = (MyClass)obj;
            return myClass.GetName();
        };
     
        property.Set = (obj, val) =>
        {
            MyClass myClass = (MyClass)obj;
            string value = (string)val;
            myClass.SetName(value);
        };
     
        ti.Properties.Add(property);
    }

    Sérialisation conditionnelle des propriétés

    Dans certains scénarios d'utilisation, il est nécessaire que certaines valeurs par défaut ne soient pas sérialisées. Par exemple, vous ne voulez pas que 0 apparaisse dans le JSON pour certaines propriétés. Il était possible de faire fonctionner ce scénario auparavant en utilisant JsonIgnoreAttribute avec JsonIgnoreCondition.WhenWritingDefault. Le problème se pose lorsque la valeur par défaut n'est pas 0 mais quelque chose de différent, par exemple -1, ou qu'elle dépend d'un paramètre externe.

    Il est maintenant possible de définir son propre prédicat ShouldSerialize avec la condition de votre choix. Par exemple, disons qu'il esxite une propriété string et que vous voulez que N/A n'apparaisse pas dans le JSON :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // string property you'd like to customize
    JsonPropertyInfo property = ...;
     
    property.ShouldSerialize = (obj, val) =>
    {
        // in this specific example we don't use parent but it's available if needed
        MyClass parentObj = (MyClass)obj;
        string value = (string)val;
        return value != "N/A";
    };

    Ignorer les propriétés ayant un nom ou un type spécifique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    var modifier = new IgnorePropertiesWithNameOrType();
    modifier.IgnorePropertyWithType(typeof(SecretHolder));
    modifier.IgnorePropertyWithName("IrrelevantDetail");
     
    JsonSerializerOptions options = new()
    {
        TypeInfoResolver = new DefaultJsonTypeInfoResolver()
        {
            Modifiers = { modifier.ModifyTypeInfo }
        }
    };
     
    ExampleClass obj = new()
    {
        Name = "Test",
        Secret = new SecretHolder() { Value = "MySecret" },
        IrrelevantDetail = 15,
    };
     
    string output = JsonSerializer.Serialize(obj, options); // {"Name":"Test"}
     
    class ExampleClass
    {
        public string Name { get; set; }
        public SecretHolder Secret { get; set; }
        public int IrrelevantDetail { get; set; }
    }
     
    class SecretHolder
    {
        public string Value { get; set; }
    }
     
    class IgnorePropertiesWithNameOrType
    {
        private List<Type> _ignoredTypes = new List<Type>();
        private List<string> _ignoredNames = new List<string>();
     
        public void IgnorePropertyWithType(Type type)
        {
            _ignoredTypes.Add(type);
        }
     
        public void IgnorePropertyWithName(string name)
        {
            _ignoredNames.Add(name);
        }
     
        public void ModifyTypeInfo(JsonTypeInfo ti)
        {
            JsonPropertyInfo[] props = ti.Properties.Where((pi) => !_ignoredTypes.Contains(pi.PropertyType) && !_ignoredNames.Contains(pi.Name)).ToArray();
            ti.Properties.Clear();
     
            foreach (var pi in props)
            {
                ti.Properties.Add(pi);
            }
        }
    }

    Mises à jour de l'API System.Formats.Tar

    Dans la Preview 4, l'assemblage System.Formats.Tar a été introduit. Elle offre des API pour la manipulation des archives TAR. Dans la Preview 6, quelques modifications ont été apportées pour couvrir quelques cas particuliers :

    Classe spécialisée Global Extended Attributes

    La conception initiale supposait que seules les archives TAR PAX pouvaient contenir une seule entrée GEA (Global Extended Attributes) en première position, mais il a été découvert que les archives TAR peuvent contenir plusieurs entrées GEA, qui peuvent affecter toutes les entrées suivantes jusqu'à ce qu'elles rencontrent une nouvelle entrée GEA ou la fin de l'archive.

    Il a également été découvert que les entrées GEA ne doivent pas être attendues uniquement dans les archives contenant exclusivement des entrées PAX : elles peuvent apparaître dans des archives qui mélangent des entrées de différents formats. Une nouvelle classe a donc été ajoutée pour décrire une entrée GEA :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    + public sealed partial class PaxGlobalExtendedAttributesTarEntry : PosixTarEntry
    + {
    +     public PaxGlobalExtendedAttributesTarEntry(IEnumerable<KeyValuePair<string, string>> globalExtendedAttributes) { }
    +     public IReadOnlyDictionary<string, string> GlobalExtendedAttributes { get { throw null; } }
    + }

    Format d'entrée, pas format d'archive

    Puisqu'il a également été découvert que des entrées de différents formats peuvent être mélangées dans une seule archive TAR, l'enum TarFormat a été renommé TarEntryFormat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    -public enum TarFormat
    +public enum TarEntryFormat
    {
        ...
    }

    Et une nouvelle propriété a été ajoutée à TarEntry pour exposer le format de l'entrée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public abstract partial class TarEntry
    {
        ...
    +    public TarEntryFormat Format { get { throw null; } }
        ...
    }

    Changements en écriture et en lecture

    La propriété Format a été supprimée de TarReader car aucune archive n'est censée avoir toutes ses entrées dans un format unique. Étant donné que les entrées GEA sont maintenant décrites avec leur propre classe spécialisée, et que plusieurs entrées de ce type peuvent être trouvées dans une seule archive, la propriété dictionnaire du TarReader a également été supprimée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public sealed partial class TarReader : IDisposable
    {
        ...
    -    public TarFormat Format { get { throw null; } }
    -    public IReadOnlyDictionary<string, string>? GlobalExtendedAttributes { get { throw null; } }
        ...
    }

    L'ajout de la classe GEA spécialisée a également affecté TarWriter :

    • le constructeur qui prenait le dictionnaire pour une seule entrée GEA en première position a été supprimé ;
    • un nouveau constructeur qui ne prend que le flux et le booléen leaveOpen a été ajouté ;
    • le constructeur qui prend le TarFormat a été conservé, mais l'énumération a été renommée, et une valeur par défaut a été fixée à Pax. La documentation de la méthode a été modifiée pour expliquer que le paramètre format spécifié s'applique uniquement à la méthode TarWriter.WriteEntry qui ajoute une entrée à partir d'un fichier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public sealed partial class TarWriter : IDisposable
    {
        ...
    -    public TarWriter(Stream archiveStream, IEnumerable<KeyValuePair<string, string>>? globalExtendedAttributes = null, bool leaveOpen = false) { }
    +    public TarWriter(Stream archiveStream, bool leaveOpen = false) { }
    -    public TarWriter(Stream archiveStream, TarFormat archiveFormat, bool leaveOpen = false) { }
    +    public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pax, bool leaveOpen = false) { }
         public void WriteEntry(string fileName, string? entryName) { }
        ...
    }

    Création de modèles

    Contraintes

    La Preview 6 introduit le concept de contraintes dans les modèles .NET. Les contraintes permettent de définir le contexte dans lequel les modèles sont autorisés. Ce qui peut aider le moteur de modèles à déterminer quels modèles il doit afficher dans des commandes comme dotnet new list. Dans cette version, Microsoft a ajouté la prise en charge de trois types de contraintes :

    • Système d'exploitation : qui limite les modèles en fonction du système d'exploitation de l'utilisateur ;
    • Template Engine Host : qui limite les modèles en fonction de l'hôte qui exécute le Template Engine. Il s'agit généralement du .NET CLI lui-même, ou de scénarios intégrés comme la boîte de dialogue Nouveau projet dans Visual Studio/Visual Studio pour Mac ;
    • Charges de travail installées : exige que la charge de travail .NET SDK spécifiée soit installée avant que le modèle ne soit disponible.

    Dans tous les cas, la description de ces contraintes est aussi simple que l'ajout d'une nouvelle section de contraintes au fichier de configuration du modèle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    "constraints": {
           "web-assembly": {
               "type": "workload",
               "args": "wasm-tools"
           },
       }

    Actuellement, ces contraintes sont prises en charge dans le .NET CLI, et l'éauipe .NET travaille des équipes Visual Studio pour les intégrer dans les expériences de création de projets et d'éléments déjà existant.

    Cette fonctionnalité poura permettre aux utilisateurs du SDK de bénéficier d'une expérience plus cohérente, quel que soit leur choix d'éditeur, Microsft espère qu'elle facilitera le pilotage des utilisateurs vers les prérequis des modèles et qu'elle aidera à désencombrer la liste des modèles pour les scénarios courants tels que dotnet new list. Dans les futures versions de .NET 7.

    Paramètres multi-choix

    La Preview 6 ajoute également une nouvelle capacité pour les paramètres de choix ; la possibilité pour un utilisateur de spécifier plus d'une valeur dans une seule sélection. Cette fonctionnalité peut être utilisée de la même manière qu'un enum de type Flags. Voici des exemples courants de ce type de paramètre :

    • choix de plusieurs formes d'authentification sur le modèle web ;
    • choix de plusieurs plateformes cibles (ios, android, web) à la fois dans les templates maui.

    Pour adopter ce comportement, il suffit d'ajouter allowMultipleValues : true à la définition du paramètre dans la configuration du modèle. Ceci donne alors accès à un certain nombre de fonctions d'aide à utiliser dans le contenu du modèle pour détecter les valeurs spécifiques choisies par l'utilisateur.

    Unification des codes de sortie et rapports

    La Preview 6 a également unifié les codes de sortie signalés par le moteur de modèles. Cela devrait permettre aux utilisateurs qui utilisent des scripts dans leur shell de prédilection de bénéficier d'une gestion des erreurs plus cohérente. En outre, les erreurs signalées par le .NET CLI comprennent désormais un lien permettant de trouver des informations détaillées sur chaque code de sortie.

    Source : Microsoft

    Et vous ?

    Que pensez-vous des changements et des nouveautés introduits par la Preview 6 de .NET 7 ?

    Voir aussi :

    Microsoft annonce .NET 7 Preview 3, la version du framework pour la création des applications, apporte une amélioration du temps de démarrage avec la fonction Write-Xor-Execute activée de 10 à 15 %

    Microsoft annonce .NET 7 Preview 4, la version du framework pour la création des applications, elle corrige les bogues et comprend des MAJ

    Microsoft publie le premier aperçu de .NET 7 avec des optimisations continues du compilateur JIT, de nouvelles API et la prise en charge de plus de scénarios de rechargement à chaud
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  2. #2
    Chroniqueur Actualités

    Homme Profil pro
    Dirigeant
    Inscrit en
    juin 2016
    Messages
    2 623
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Dirigeant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : juin 2016
    Messages : 2 623
    Points : 57 075
    Points
    57 075
    Par défaut Microsoft publie .NET 7 Preview 7, le dernier aperçu de la nouvelle version du framework
    Microsoft publie .NET 7 Preview 7, le dernier aperçu de la nouvelle version du framework avant la sortie de la première version candidate
    cet aperçu apporte de nouvelles améliorations au framework

    Microsoft a publié mardi .NET 7 Preview 7. L'entreprise a annoncé qu'il s'agit du dernier aperçu de .NET 7 et que la prochaine version sera la première release candidate (RC). Cet aperçu de .NET 7 comprend des améliorations de System.LINQ, des permissions de fichiers Unix, des structures de bas niveau, de la génération de sources p/Invoke, de la génération de code et des websockets. L'aperçu 7 a été testé avec Visual Studio 17.4 Preview 1, qui a également été publié mardi en même temps que la version finale Visual Studio v17.3. Le lancement de la version stable de .NET 7 est prévu pour le 10 novembre 2022.

    Lorsque le développement de .NET 7 a commencé, Microsoft a expliqué à la communauté que cette nouvelle version unifiera enfin tous les composants disparates des outils de développement .NET, permettant aux développeurs de créer tous les types d'applications - bureautiques, mobiles, Web et autres - sur la même bibliothèque de classes de base (BCL), le même moteur d'exécution et les mêmes compilateurs. C'était en fait l'objectif de .NET 5 - qui succède aux offres .NET Core - lorsqu'il a fait ses débuts en novembre 2020. Mais des problèmes de développement exacerbés par la pandémie n'ont pas permis d'atteindre cet objectif.

    En effet, tous les éléments prévus n'ont pas été intégrés à .NET 5 et ont été reportés jusqu'à l'arrivée de .NET 6 en novembre 2021 en tant que version LTS (Long Term Support). Mais même à ce moment-là, l'effort d'unification global de Microsoft était incomplet, car certains composants, tels que .NET Multi-platform App UI (.NET MAUI), n'ont pas respecté le calendrier. .NET MAUI a depuis atteint la disponibilité générale, et l'unification complète est désormais attendue pour novembre. Lors de la célébration des 20 ans de .NET en février dernier, Microsoft a réitéré son intention d'unifier tous les composants du framework à partir de .NET 7.

    Nom : images.png
Affichages : 18533
Taille : 50,0 Ko

    « .NET 7 s'appuie sur la base établie par .NET 6, qui comprend un ensemble unifié de bibliothèques de base, de runtime et de SDK, une expérience de développement simplifiée et une productivité accrue des développeurs. Les principaux domaines d'intérêt de .NET 7 comprennent une meilleure prise en en charge des scénarios cloud native, des outils facilitant la mise à niveau des projets existants et la simplification de l'expérience du développeur en facilitant le travail avec les conteneurs », a écrit Jeremy Likness de l'équipe .NET à propos de cette version. En gros, .NET 7 vise à faciliter le développement d'applications cloud natives et la conteneurisation.

    Dans le cadre de l'aperçu 7, Likness a déclaré mardi que l'équipe de développement s'est concentrée sur l'amélioration de System.LINQ, des permissions de fichiers Unix, des structures de bas niveau, de la génération de sources p/Invoke, de la génération de code et des websockets. Tous ces éléments spécifiques relèvent des conseils généraux fournis sur le site Themes of .NET. Voici ci-dessous les points forts de .NET 7 Preview 7 :

    Commande simplifiée avec System.LINQ

    System.Linq comprend maintenant de nouvelles méthodes, Order et OrderDescending, qui sont utilisées pour commander un IEnumerable en fonction de T. IQueryable supporte également ces méthodes maintenant.

    Avant le changement

    Auparavant, vous deviez appeler OrderBy/OrderByDescending en faisant référence à la valeur propre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var data = new[] { 2, 1, 3 };
    var sorted = data.OrderBy(static e => e);
    var sortedDesc = data.OrderByDescending(static e => e);

    Après le changement

    Maintenant, vous pouvez écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var data = new[] { 2, 1, 3 };
    var sorted = data.Order();
    var sortedDesc = data.OrderByDescending();

    Prise en charge des modes de fichiers Unix

    Auparavant, .NET ne disposait d'aucun support intégré pour l'obtention et la définition des autorisations de fichiers Unix, qui contrôlent les utilisateurs autorisés à lire, écrire et exécuter des fichiers et des répertoires. Il n'est pas toujours facile d'invoquer manuellement les syscalls, car certains sont exposés différemment selon les distributions. Par exemple, sur Ubuntu, vous pouvez avoir à pinvoke à __xstat, sur RedHat à stat, et ainsi de suite. Selon l'équipe, c'est la raison pour laquelle il est important de disposer d'une API .NET de première classe. Dans l'aperçu 7, l'équipe a introduit un nouveau type enum :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public enum UnixFileMode
    {
        None,
        OtherExecute, OtherWrite, OtherRead,
        GroupExecute, GroupWrite, GroupRead,
        UserExecute, UserWrite, UserRead,
         ...
    }

    Elle a également ajouté les API File.GetUnixFileMode et File.SetUnixFileMode qui permettent d'obtenir et de définir le mode de fichier sur un chemin ou un handle (descripteurs de fichiers). Ainsi qu'une nouvelle propriété sur FileInfo et DirectoryInfo nommée UnixFileMode. Il existe également une nouvelle surcharge de Directory.CreateDirectory et une nouvelle propriété sur FileStreamOptions pour vous permettre de créer un répertoire ou un fichier avec un mode particulier en une seule fois.

    Selon l'équipe, lorsque vous les utilisez, umask est toujours appliqué, comme si vous aviez créé le répertoire ou le fichier dans votre Shell. Voici un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // Create a new directory with specific permissions
    Directory.CreateDirectory("myDirectory", UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
     
    // Create a new file with specific permissions
    FileStreamOptions options = new()
    {
        Access = FileAccess.Write,
        Mode = FileMode.Create,
        UnixCreateMode =  UnixFileMode.UserRead | UnixFileMode.UserWrite,
    };
    using FileStream myFile = new FileStream("myFile", options);
     
    // Get the mode of an existing file
    UnixFileMode mode = File.GetUnixFileMode("myFile");
     
    // Set the mode of an existing file
    File.SetUnixFileMode("myFile", UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);

    Améliorations des structures de bas niveau : prise en charge du champ ref

    Les moteurs d'exécution .NET 7 prennent désormais pleinement en charge les champs ref dans les types ByRefLike (c'est-à-dire les structures ref). Grâce à cette fonctionnalité, les types qui nécessitaient auparavant une gestion spécialisée dans les moteurs d'exécution (par exemple, Span<T> et ReadOnlySpan<T>) peuvent désormais être entièrement implémentés en C#.

    Générateur de sources LibraryImport P/Invoke

    Le générateur de sources LibraryImport est désormais disponible de manière supportée pour tous les utilisateurs. Fruit de plus de 18 mois de travail, ce générateur de sources est conçu pour remplacer directement la majorité des utilisations de DllImport, tant dans le produit d'exécution que dans le code utilisateur. L'équipe indique que les bibliothèques .NET ont toutes adopté LibraryImport et sont livrées avec du code de marshalling généré par les sources depuis .NET 7 Preview 1.

    Le générateur source est livré avec le TFM (target framework moniker) .NET 7 et est facilement disponible pour la consommation. Pour bénéficier de la mise en correspondance générée par les sources, remplacez l'utilisation de DllImport par LibraryImport. Il existe des analyseurs et des correcteurs qui peuvent vous aider dans ce processus. Voici un exemple :

    Avant la prise en charge de LibraryImport

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static class Native
    {
        [DllImport(nameof(Native), CharSet = CharSet.Unicode)]
        public extern static string ToLower(string str);
    }

    Avec la prise en charge de LibraryImport

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static class Native
    {
        [LibraryImport(nameof(Native), StringMarshalling = StringMarshalling.Utf16)]
        public static partial string ToLower(string str);
    }

    L'équipe a indiqué qu'il existe un analyseur et un correcteur de code pour convertir automatiquement vos attributs DllImport en LibraryImport. Pour l'aperçu 7, il s'agit d'un opt-in. Ajoutez dotnet_diagnostic.SYSLIB1054.severity = suggestion à votre fichier EditorConfig pour activer l'analyseur de conversion en tant que diagnostic.

    Amélioration du comportement de ClientWebSocket

    Auparavant, ClientWebSocket ne fournissait aucun détail sur la réponse de mise à niveau. Cependant, les informations sur les en-têtes de réponse et le code d'état peuvent être importantes dans les scénarios d'échec et de réussite. En cas d'échec, le code d'état peut aider à faire la distinction entre les erreurs récupérables et non récupérables (le serveur ne prend pas du tout en charge les websockets ou il s'agit simplement d'une petite erreur transitoire).

    Les en-têtes peuvent aussi contenir des informations supplémentaires sur la manière de gérer la situation. Les en-têtes sont également utiles même en cas de connexion réussie d'un websocket. ils peuvent contenir un jeton lié à une session, des informations relatives à la version du sous-protocole, etc.

    Support

    .NET 7 est une version de support à court terme (Short Term Support - STS), ce qui signifie qu'elle bénéficiera d'un support et de correctifs gratuits pendant 18 mois à compter de sa date de sortie. L'équipe indique que la qualité de toutes les versions est la même. La seule différence est la durée de l'assistance. Enfin, l'équipe explique que .NET 7 Preview 7 a été testé avec Visual Studio 17.4 Preview 1.

    Elle recommande d'utiliser les builds du canal preview si vous voulez essayer .NET 7 avec les produits de la famille Visual Studio. Si vous êtes sur macOS, elle recommande d'utiliser la dernière version de Visual Studio 2022 pour Mac. Microsoft prévoit de lancer .NET 7 lors d'un événement qui se tiendra du 8 au 10 novembre 2022.

    Source : .NET 7 Preview 7

    Et vous ?

    Que pensez-vous des nouveautés et améliorations introduites par .NET 7 Preview 7 ?

    Voir aussi

    Microsoft annonce .NET 7 Preview 6, la version du framework pour la création des applications, améliore les convertisseurs de type, personnalise des contrats JSON

    Microsoft annonce .NET 7 Preview 4, la version du framework pour la création des applications, elle corrige les bogues et comprend des MAJ

    Microsoft annonce .NET 7 Preview 3, la version du framework pour la création des applications, apporte une amélioration du temps de démarrage avec la fonction Write-Xor-Execute activée de 10 à 15 %

    Microsoft publie le premier aperçu de .NET 7 avec des optimisations continues du compilateur JIT, de nouvelles API et la prise en charge de plus de scénarios de rechargement à chaud

    Microsoft célèbre les 20 ans de .NET, son Framework de développement, les dépôts .NET seraient dans le top 30 des projets open source à plus haute vélocité sur GitHub depuis 2017
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  3. #3
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    mai 2019
    Messages
    1 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Rédacteur technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : mai 2019
    Messages : 1 016
    Points : 20 660
    Points
    20 660
    Par défaut .NET : la version 7 du framework de développement d'applications serait la plus rapide de tous les temps
    .NET : la version 7 du framework de développement d'applications serait la plus rapide de tous les temps,
    bien devant .NET 6 qui apportait jusqu'à 40 % de gain de vitesse par rapport à .NET 5

    Dans un article rédigé le 22 novembre de l’année dernière, nous indiquons que .NET 6 pourrait apporter jusqu'à 40 % de gain de vitesse par rapport .NET 5. Les tests de mise en cache et de boucles serrées serraient jusqu'à 30 % plus rapide. Comme dans les versions précédentes de .NET, les performances sont un élément clé qui imprègne toute la pile de .NET. Aujourd’hui, alors que la communauté des développeurs .NET attend une version candidate de .NET 7, Microsoft annonce par le truchement de Stephen Toub, Développeur au sein de l'équipe .NET de Microsoft, l’amélioration des performances de .NET 7.

    « .NET 6 est vraiment le .NET le plus rapide à ce jour », avait déclaré Alex Yakunin, Directeur technique chez ServiceTitan, une plateforme de technologie logicielle. Selon Yakunin, .NET 6 apporte jusqu'à 40 % de gain de vitesse par rapport .NET 5. Un peu plus tôt le 9 novembre, Microsoft a annoncé .NET 6, comme la version la plus rapide à ce jour avec prise en charge des puces Apple Silicon, des containers Windows isolés des processus et une amélioration des E/S de fichiers.

    Nom : donet.png
Affichages : 4431
Taille : 1,3 Ko

    « Bienvenue à .NET 6. La version d'aujourd'hui est le résultat d'un peu plus d'un an d'efforts de la part de l'équipe .NET et de la communauté. .NET 6 est la première version qui prend en charge de manière native les processeurs Apple Silicon (Arm64) et a également été améliorée pour Windows Arm64 », avait alors déclaré Richard Lander, responsable de programme au sein de l'équipe .NET Core.

    Suite à des tests de comparaison entre .NET 6 et .NET 5, Alex Yakunin conclut que :

    • les tests de mise en cache et de boucles serrées serraient jusqu'à 30 % plus rapide avec .NET 6 ;
    • l’ajout du cache de Fusion à une API web ordinaire, obtient une accélération de 15 % avec .NET 6 ;
    • le test du pipeline HTTP "classique" (HttpClient frappant un contrôleur ASP.NET Core qui héberge un service EF Core de type CRUD) obtient une accélération d'environ 4,5 %.

    Lorsque le développement de .NET 7 a commencé, Microsoft a expliqué à la communauté que cette nouvelle version unifiera enfin tous les composants disparates des outils de développement .NET, permettant aux développeurs de créer tous les types d'applications - bureautiques, mobiles, Web et autres - sur la même bibliothèque de classes de base (BCL), le même moteur d'exécution et les mêmes compilateurs. C'était en fait l'objectif de .NET 5 - qui succède aux offres .NET Core - lorsqu'il a fait ses débuts en novembre 2020. Mais des problèmes de développement exacerbés par la pandémie n'ont pas permis d'atteindre cet objectif.

    En effet, tous les éléments prévus n'ont pas été intégrés à .NET 5 et ont été reportés jusqu'à l'arrivée de .NET 6 en novembre 2021 en tant que version LTS (Long Term Support). Mais même à ce moment-là, l'effort d'unification global de Microsoft était incomplet, car certains composants, tels que .NET Multi-platform App UI (.NET MAUI), n'ont pas respecté le calendrier. .NET MAUI a depuis atteint la disponibilité générale, et l'unification complète est désormais attendue pour novembre. Lors de la célébration des 20 ans de .NET en février dernier, Microsoft a réitéré son intention d'unifier tous les composants du framework à partir de .NET 7.

    Maintenant qu'une version candidate de .NET 7 est sur le point de sortir, Microsoft estime que c'est le bon moment pour discuter des questions de performances. « Au cours de l'année écoulée, chaque fois que j'ai passé en revue un RP susceptible d'avoir un impact positif sur les performances, j'ai copié ce lien dans un journal que je tiens à jour. Il y a quelques semaines, j'ai été confronté à une liste de près de 1 000 RP ayant un impact sur les performances. », a écrit Stephen Toub. « .NET 7 est rapide. Vraiment rapide. Un millier de RP ayant un impact sur les performances ont été introduits dans les bibliothèques d'exécution et de base dans cette version, sans parler de toutes les améliorations apportées à ASP.NET Core, Windows Forms, Entity Framework et au-delà. C'est le .NET le plus rapide de tous les temps », poursuit-il.

    Nom : BenchMarck.jpg
Affichages : 2278
Taille : 58,7 Ko

    Configuration

    Les microbenchmarks utilisés dans ce post utilisent benchmarkdotnet. Pour suivre facilement sa propre validation, voici une configuration très simple pour les benchmarks. Créez un nouveau projet C# :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dotnet new console -o benchmarks
    cd benchmarks

    Le nouveau répertoire benchmarks contiendra un fichier benchmarks.csproj et un fichier Program.cs. Remplacez le contenu de benchmarks.csproj par ceci :

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <Project Sdk="Microsoft.NET.Sdk">
     
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFrameworks>net7.0;net6.0</TargetFrameworks>
        <LangVersion>Preview</LangVersion>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
        <ServerGarbageCollection>true</ServerGarbageCollection>
      </PropertyGroup>
     
      <ItemGroup>
        <PackageReference Include="benchmarkdotnet" Version="0.13.2" />
      </ItemGroup>
     
    </Project>


    Pour chaque benchmark inclus dans cet article, il est possible de copier et coller le code dans cette classe de test, et exécuter les benchmarks. Par exemple, pour exécuter un benchmark comparant les performances sur .NET 6 et .NET 7 :

    dotnet run -c Release -f net6.0 --filter '**' --runtimes net6.0 net7.0

    Cette commande dit « construire les benchmarks en ciblant .NET 6, puis exécuter tous les benchmarks à la fois sur .NET 6 et .NET 7 ». Ou pour exécuter uniquement sur .NET 7 :

    dotnet run -c Release -f net7.0 --filter '**' --runtimes net7.0

    qui, au lieu de cela, construit en ciblant la surface de .NET 7 et ne s'exécute qu'une seule fois contre .NET 7. Vous pouvez effectuer cette opération sous Windows, Linux ou macOS. Sauf indication contraire (par exemple, lorsque les améliorations sont spécifiques à Unix et que j'exécute les benchmarks sur Linux), les résultats que partagés ici ont été enregistrés sur Windows 11 64 bits mais ne sont pas spécifiques à Windows et devraient montrer des différences relatives similaires sur les autres systèmes d'exploitation également.

    La publication de la première version candidate de .NET 7 est imminente. Toutes les mesures présentées dans cet article ont été recueillies avec une version quotidienne récente de .NET 7 RC1. Notons qu'il s'agit de microbenchmarks. On s'attend à ce que des matériels différents, des versions différentes et des systèmes d'exploitation puissent affecter les chiffres en question.

    Regex

    Avant .NET 5, l'implémentation de Regex n'avait pratiquement pas été modifiée pendant un certain temps. Dans .NET 5, Microsoft l'a ramenée à un niveau équivalent, voire supérieur, à celui de plusieurs autres implémentations de l'industrie du point de vue des performances. Avec .NET 7, Microsoft a fait un grand pas en avant.

    RegexOptions.NonBacktracking (non retour en arrière)

    Stephen Toub commence par présenter l'une des plus grandes nouveautés de Regex, la nouvelle implémentation de RegexOptions.NonBacktracking. Selon le développeur .NET, RegexOptions.NonBacktracking bascule le traitement de Regexvers l'utilisation d'un nouveau moteur basé sur les automates finis. Il a deux modes d'exécution principaux, l'un qui repose sur les DFA (automates finis déterministes) et l'autre sur les NFA (automates finis non déterministes). Les deux implémentations offrent une garantie très précieuse : le temps de traitement est linéaire par rapport à la longueur de l'entrée.

    Alors qu'un moteur de backtracking (qui est ce que Regex utilise si NonBacktracking n'est pas spécifié) peut rencontrer une situation connue sous le nom de backtracking catastrophique, où des expressions problématiques combinées avec une entrée problématique peuvent résulter en un traitement exponentiel dans la longueur de l'entrée, NonBacktracking garantit qu'il ne fera jamais qu'une quantité de travail constante amortie par caractère dans l'entrée. Dans le cas d'un DFA, cette constante est très petite. Avec un NFA, cette constante peut être beaucoup plus grande, en fonction de la complexité du motif, mais pour un motif donné, le travail reste linéaire par rapport à la longueur de l'entrée.

    Un nombre important d'années de développement a été consacré à l'implémentation de NonBacktracking, qui a été initialement ajoutée à dotnet/runtime dans dotnet/runtime#60607. Cependant, la recherche et l'implémentation originales de cette implémentation provenaient en fait de Microsoft Research (MSR), et étaient disponibles sous la forme d'un paquetage expérimental sous la forme de la bibliothèque Symbolic Regex Matcher (SRM) publiée par MSR. Il est encore possible d'en voir des vestiges dans le code actuel de .NET 7, mais il a évolué de manière significative, en étroite collaboration entre les développeurs de l'équipe .NET et les chercheurs de MSR (avant d'être intégré dans dotnet/runtime, il a été incubé pendant plus d'un an dans dotnet/runtimelab, où le code SRM original a été introduit via dotnet/runtimelab#588 ).

    Cette implémentation est basée sur la notion de dérivés d'expressions régulières, un concept qui existe depuis des décennies et qui a été considérablement amélioré pour cette implémentation. Les dérivés de Regexconstituent la base de la construction des automates utilisés pour traiter les entrées. L'idée de base est assez simple : prenez une regex et traitez un seul caractère... quelle est la nouvelle regex que vous obtenez pour décrire ce qui reste après avoir traité ce seul caractère ? C'est la dérivée.

    Par exemple, si l'on prend la regex \w{3} pour correspondre à trois caractères de mot, si on l'applique au prochain caractère d'entrée 'a', le premier \w sera supprimé, ce qui nous laissera le dérivé \w{2}. Simple, non ? Qu'en est-il de quelque chose de plus compliqué, comme l'expression .*(the|he). Que se passe-t-il si le prochain caractère est un t ? Eh bien, il est possible que le t soit consommé par le .* au début du motif, auquel cas la regex restante serait exactement la même que celle de départ (.*(the|he)), puisqu'après avoir fait correspondre le t, nous pourrions toujours faire correspondre exactement la même entrée que sans le t. Mais, le t pourrait aussi avoir fait partie de la correspondance avec the, et appliqué au the, nous enlèverions le t et il resterait le he, donc maintenant notre dérivé est .*(the|he)|he. Mais qu'en est-il du he dans l'alternance originale ? t ne correspond pas à h, donc la dérivée ne serait rien, ce que nous exprimerons ici comme une classe de caractères vide, nous donnant .*(the|he)|he|[]. Bien sûr, dans le cadre d'une alternance, ce "rien" à la fin est un nop, et nous pouvons donc simplifier l'ensemble de la dérivation en .*(the|he)|he... terminé. C'était tout en appliquant le modèle original contre un t suivant. Et si c'était contre un h à la place ? En suivant la même logique que pour le t, on obtient cette fois .*(the|he)|e. Et ainsi de suite. Et si on commençait plutôt par le dérivé du h et que le caractère suivant était un e ? Dans ce cas, nous prenons le motif .*(the|he)|e et l'appliquons à e. Dans le cas du côté gauche de l'alternance, il peut être consommé par le .* (mais ne correspond ni à t ni à h), et nous nous retrouvons donc avec la même sous-expression. Mais contre le côté droit de l'alternance, e correspond à e, ce qui nous laisse avec la chaîne vide () : .*(the|he)|(). Lorsqu'un motif est "nullable" (il peut correspondre à la chaîne vide), il peut être considéré comme une correspondance. Nous pouvons visualiser le tout sous la forme d'un graphique, avec des transitions pour chaque caractère d'entrée vers la dérivée qui résulte de son application.

    Nom : regex.jpg
Affichages : 2234
Taille : 23,5 Ko

    Selon Stephen Toub, c'est exactement comme cela que NonBacktracking construit les DFAs qu'il utilise pour traiter les entrées. Pour chaque construction de regex (concaténations, alternances, boucles, etc.), le moteur sait comment dériver la regex suivante sur la base du caractère évalué. Cette application est effectuée de manière paresseuse, de sorte que nous avons un état de départ initial (le motif original), puis lorsque nous évaluons le prochain caractère en entrée, il regarde s'il existe déjà un dérivé disponible pour cette transition : s'il y en a un, il le suit, et s'il n'y en a pas, il dérive dynamiquement/lentement le prochain nœud du graphe. En gros, c'est comme ça que ça fonctionne.

    Stephen Touble montre qu'il existe une tonne de complications et d'ingéniosité pour rendre le moteur efficace. L'un de ces exemples est le compromis entre la consommation de mémoire et le débit. Étant donné la possibilité d'avoir n'importe quel caractère en entrée, il est possible d'avoir effectivement ~65000 transitions à partir de chaque nœud (par exemple, chaque nœud pourrait avoir besoin d'une table d'éléments ~65000) ; cela augmenterait considérablement la consommation de mémoire.

    Cependant, si on a réellement autant de transitions, il est très probable qu'une majorité significative d'entre elles pointeraient vers le même noeud cible. Ainsi, NonBacktracking maintient ses propres regroupements de caractères dans ce qu'il appelle des minterms. Si deux caractères ont exactement la même transition, ils font partie du même minterm. Les transitions sont alors construites en termes de mintermes, avec au maximum une transition par minterm à partir d'un nœud donné. Lorsque le prochain caractère d'entrée est lu, il est associé à un ID de minterm, puis trouve la transition appropriée pour cet ID ; un niveau supplémentaire d'indirection afin d'économiser une quantité potentiellement énorme de mémoire. Ce mappage est géré via un tableau de bitmaps pour l'ASCII et une structure de données efficace connue sous le nom de diagramme de décision binaire (BDD) pour tout ce qui est supérieur à 0x7F.

    Comme indiqué, le moteur non rétroactif est linéaire par rapport à la longueur de l'entrée. Mais cela ne signifie pas qu'il examine toujours chaque caractère en entrée exactement une fois. Si Regex.IsMatch, c'est le cas ; après tout, IsMatch a seulement besoin de déterminer s'il y a une correspondance et n'a pas besoin de calculer d'autres informations, comme l'endroit où la correspondance commence ou se termine, toute information sur les captures, etc. Ainsi, le moteur peut simplement utiliser ses automates pour parcourir le long de l'entrée, en se déplaçant de nœud en nœud dans le graphe jusqu'à ce qu'il arrive à un état final ou qu'il n'ait plus d'entrée.

    D'autres opérations, cependant, exigent qu'il recueille plus d'informations. Regex.Match doit tout calculer, ce qui peut impliquer de multiples déplacements sur l'entrée. Dans l'implémentation initiale, l'équivalent de Match devait toujours effectuer trois passages : faire correspondre vers l'avant pour trouver la fin d'une correspondance, puis faire correspondre une copie inversée du motif à l'envers à partir de cette position de fin afin de trouver où la correspondance commence réellement, et enfin parcourur encore une fois vers l'avant à partir de cette position de départ connue pour trouver la position de fin réelle.

    Cependant, avec dotnet/runtime#68199, à moins que des captures ne soient nécessaires, cela peut maintenant être fait en deux passes seulement : une fois en avant pour trouver la position finale garantie de la correspondance, et ensuite une fois en arrière pour trouver sa position de départ. Et dotnet/runtime#65129 a ajouté le support des captures, que l'implémentation originale n'avait pas non plus.

    Cette prise en charge des captures ajoute une troisième passe, de sorte qu'une fois que les limites du match sont connues, le moteur exécute la passe avant une fois de plus, mais cette fois avec une "simulation" basée sur la NFA qui est capable d'enregistrer les « effets de capture » sur les transitions. Tout ceci permet à l'implémentation du nonbacktracking d'avoir exactement la même sémantique que les moteurs de backtracking, produisant toujours les mêmes correspondances dans le même ordre avec les mêmes informations de capture. La seule différence à cet égard est que, alors qu'avec les moteurs backtracking, les groupes de capture à l'intérieur des boucles stockent toutes les valeurs capturées à chaque itération de la boucle, seule la dernière itération est stockée avec l'implémentation non backtracking. En plus de cela, il y a quelques constructions que l'implémentation non backtracking ne supporte tout simplement pas, de sorte que toute tentative d'utiliser l'une d'entre elles échouera lors de la construction de la Regex, par exemple les rétro-références et les lookarounds.

    JIT

    Il est essentiel de pouvoir comprendre exactement quel code assembleur est généré par le JIT lorsqu'il s'agit d'affiner le code de bas niveau sensible aux performances. Il existe plusieurs façons d'accéder à ce code assembleur. L'outil en ligne sharplab.io est incroyablement utile pour cela ; cependant, il ne cible actuellement qu'une seule version, donc actuellement, nous ne pouvons voir que le résultat pour .NET 6, ce qui le rend difficile à utiliser pour des comparaisons A/B. Les solutions les plus flexibles impliquent d'obtenir ce code d'assemblage localement, car cela permet de comparer toutes les versions ou constructions locales souhaitées avec toutes les configurations et tous les commutateurs.

    Une approche courante consiste à utiliser le [DisassemblyDiagnoser] de benchmarkdotnet. Il suffit d'ajouter l'attribut [DisassemblyDiagnoser] à votre classe de test : benchmarkdotnet trouvera le code d'assemblage généré pour vos tests et une partie des fonctions qu'ils appellent, et affichera le code d'assemblage trouvé sous une forme lisible par l'homme. Par exemple, ce test est lancé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    using BenchmarkDotNet.Attributes;
    using BenchmarkDotNet.Running;
    using System;
     
    [DisassemblyDiagnoser]
    public partial class Program
    {
        static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
     
        private int _a = 42, _b = 84;
     
        [Benchmark]
        public int Min() => Math.Min(_a, _b);

    avec :

    dotnet run -c Release -f net7.0 --filter '**'

    En plus de l'exécution normale des tests et de la synchronisation, benchmarkdotnet produit également un fichier Program-asm.md qui contient ceci :

    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ; Program.Min()
           mov       eax,[rcx+8]
           mov       edx,[rcx+0C]
           cmp       eax,edx
           jg        short M00_L01
           mov       edx,eax
    M00_L00:
           mov       eax,edx
           ret
    M00_L01:
           jmp       short M00_L00
    ; Total bytes of code 17

    Cette prise en charge a été récemment améliorée dans dotnet/benchmarkdotnet#2072, qui permet de passer une liste de filtres en ligne de commande à benchmarkdotnet pour lui dire exactement quel code d'assemblage des méthodes doit être vidé.

    Avec une version "déboguée" ou "vérifiée" du runtime .NET ("vérifiée" est une version dont les optimisations sont activées mais qui inclut toujours les assertions), et plus particulièrement de clrjit.dll, une autre approche intéressante consiste à définir une variable d'environnement qui permet au JIT lui-même de produire une description lisible par les humains de tout le code d'assemblage qu'il émet. Cette méthode peut être utilisée avec n'importe quel type d'application, car elle fait partie du JIT lui-même plutôt que d'un outil spécifique ou d'un autre environnement, elle permet de montrer le code que le JIT génère à chaque fois qu'il génère du code (par exemple, s'il compile d'abord une méthode sans optimisation, puis la recompile plus tard avec optimisation). Le (gros) inconvénient, bien sûr, est qu'il nécessite une version non publiée du runtime, ce qui signifie généralement que l'utilisateur doit le construire soi-même à partir des sources du dépôt dotnet/runtime.

    À partir de dotnet/runtime#73365, le support du dumping d'assemblage est maintenant disponible dans les versions publiées également, ce qui signifie qu'il fait simplement partie de .NET 7 et que l'utilisateur n'a pas besoin de quelque chose de spécial pour l'utiliser. Pour s'en convaincre, essayons de créer une application simple du type « hello world » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    using System;
     
    class Program
    {
        public static void Main() => Console.WriteLine("Hello, world!");
    }
    et le construire (par exemple, dotnet build -c Release). Ensuite, définissez la variable d'environnement DOTNET_JitDisasm sur le nom de la méthode qui nous intéresse, dans ce cas Main (la syntaxe exacte autorisée est plus permissive et permet l'utilisation de caractères génériques, de noms d'espaces de noms et de classes facultatifs, etc.) :

    $env:DOTNET_JitDisasm="Main"

    Dans la console :

    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    ; Assembly listing for method Program:Main()
    ; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
    ; Tier-0 compilation
    ; MinOpts code
    ; rbp based frame
    ; partially interruptible
     
    G_M000_IG01:                ;; offset=0000H
           55                   push     rbp
           4883EC20             sub      rsp, 32
           488D6C2420           lea      rbp, [rsp+20H]
     
    G_M000_IG02:                ;; offset=000AH
           48B9D820400A8E010000 mov      rcx, 0x18E0A4020D8
           488B09               mov      rcx, gword ptr [rcx]
           FF1583B31000         call     [Console:WriteLine(String)]
           90                   nop
     
    G_M000_IG03:                ;; offset=001EH
           4883C420             add      rsp, 32
           5D                   pop      rbp
           C3                   ret
     
    ; Total bytes of code 36
     
    Hello, world!

    Cela est extrêmement utile pour l'analyse et le réglage des performances, même pour des questions aussi simples.

    Remplacement On-Stack - OSR

    Le remplacement à la volée ou OSR est l'une des fonctionnalités les plus intéressantes du JIT dans .NET 7. Mais pour bien comprendre l'OSR, il faut d'abord comprendre la compilation étagée.

    L'un des problèmes auxquels un environnement géré avec un compilateur JIT doit faire face est le compromis entre le démarrage et le débit. Historiquement, le travail d'un compilateur d'optimisation est d'optimiser, afin de permettre le meilleur débit possible de l'application ou du service une fois en cours d'exécution. Mais une telle optimisation nécessite une analyse, prend du temps, et l'exécution de tout ce travail entraîne une augmentation du temps de démarrage, car tout le code sur le chemin de démarrage (par exemple, tout le code qui doit être exécuté avant qu'un serveur web puisse répondre à la première demande) doit être compilé.

    Un compilateur JIT doit donc faire des compromis : un meilleur débit au prix d'un temps de démarrage plus long, ou un meilleur temps de démarrage au prix d'un débit réduit. Pour certains types d'applications et de services, le compromis est facile à faire, par exemple si le service démarre une fois et fonctionne pendant des jours, quelques secondes supplémentaires de temps de démarrage n'ont pas d'importance, ou si on a une application console qui va faire un calcul rapide et sortir, le temps de démarrage est tout ce qui compte.

    Mais comment le JIT peut-il savoir dans quel scénario il se trouve, et voulons-nous vraiment que chaque développeur doive connaître ce genre de paramètres et de compromis et configurer chacune de ses applications en conséquence ? L'une des réponses à cette question a été la compilation en amont sur le temps, qui a pris diverses formes dans .NET. Par exemple, toutes les bibliothèques de base sont crossgen, c'est-à-dire qu'elles ont été exécutées par un outil qui produit le format R2R, ce qui permet d'obtenir des binaires contenant du code d'assemblage qui ne nécessite que des modifications mineures pour être réellement exécuté ; le code ne peut pas être généré pour chaque méthode, mais suffisamment pour réduire de manière significative le temps de démarrage.

    Bien sûr, ces approches ont leurs propres inconvénients, par exemple, l'une des promesses d'un compilateur JIT est qu'il peut tirer parti de la connaissance de la machine / du processus actuel afin de l'optimiser au mieux. Ainsi, par exemple, les images R2R doivent supposer un certain jeu d'instructions de base (par exemple, quelles instructions de vectorisation sont disponibles) alors que le JIT peut voir ce qui est réellement disponible et utiliser le meilleur. La « compilation hiérarchisée » apporte une autre réponse, utilisable avec ou sans ces autres solutions de compilation en avance sur le temps (AOT).

    L''idée de la compilation hiérarchisé est simple : elle permet au JIT de compiler le même code plusieurs fois. La première fois, le JIT peut utiliser aussi peu d'optimisations que possible (une poignée d'optimisations peuvent en fait rendre le débit du JIT plus rapide, donc il est toujours utile de les appliquer), produisant un code assembleur relativement peu optimisé mais très rapide. Et lorsqu'il le fait, il peut ajouter des instruments dans l'assemblage pour suivre la fréquence d'appel des méthodes.

    Il s'avère que de nombreuses fonctions utilisées sur un chemin de démarrage ne sont invoquées qu'une fois ou peut-être une poignée de fois, et il faudrait plus de temps pour les optimiser que pour les exécuter sans optimisation. Ensuite, lorsque l'instrumentation de la méthode déclenche un certain seuil, par exemple une méthode ayant été exécutée 30 fois, un élément du travail est mis en file d'attente pour recompiler cette méthode, mais cette fois avec toutes les optimisations que le JIT peut lui apporter. C'est ce qu'on appelle affectueusement le tiering up.

    Une fois la recompilation terminée, les sites d'appel de la méthode sont corrigés avec l'adresse du nouveau code assembleur hautement optimisé, et les invocations futures emprunteront le chemin rapide. Ainsi, nous obtenons un démarrage plus rapide et un débit soutenu plus rapide. Du moins, c'est ce que l'on espère.

    Les méthodes qui n'entrent pas dans ce moule posent toutefois problème. S'il est vrai que de nombreuses méthodes sensibles aux performances sont relativement rapides et exécutées de très nombreuses fois, il existe également un grand nombre de méthodes sensibles aux performances qui ne sont exécutées qu'une poignée de fois, voire une seule, mais dont l'exécution prend beaucoup de temps, voire la durée de tout le processus : les méthodes avec boucles. Par conséquent, par défaut, la compilation étagée n'est pas appliquée aux boucles, bien qu'elle puisse être activée en fixant la variable d'environnement DOTNET_TC_QuickJitForLoops à 1. Les effets peuvent être observés en essayant cette application console simple avec .NET 6. Avec les paramètres par défaut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class Program
    {
        static void Main()
        {
            var sw = new System.Diagnostics.Stopwatch();
            while (true)
            {
                sw.Restart();
                for (int trial = 0; trial < 10_000; trial++)
                {
                    int count = 0;
                    for (int i = 0; i < char.MaxValue; i++)
                        if (IsAsciiDigit((char)i))
                            count++;
                }
                sw.Stop();
                Console.WriteLine(sw.Elapsed);
            }
     
            static bool IsAsciiDigit(char c) => (uint)(c - '0') <= 9;
        }
    }
    L'optimisation guidée par le profil (PGO) existe depuis longtemps, dans un grand nombre de langages et de compilateurs. L'idée de base est de compiler l'application, en demandant au compilateur d'injecter des instruments dans l'application pour traquer divers éléments d'information intéressants. Vous mettez ensuite votre application à l'épreuve, en exécutant divers scénarios courants, ce qui amène l'instrumentation à profiler ce qui se passe lorsque l'application est exécutée, et les résultats sont ensuite enregistrés.

    L'application est ensuite recompilée, en renvoyant les résultats de l'instrumentation au compilateur, ce qui lui permet d'optimiser l'application en fonction de la manière dont elle est censée être utilisée. Cette approche de PGO est appelée PGO statique, car les informations sont glanées avant le déploiement réel, et c'est quelque chose que .NET fait sous diverses formes depuis des années. Cependant, selon Stephen Toub, le développement vraiment intéressant de .NET est le PGO dynamique, qui a été introduit dans .NET 6, mais désactivé par défaut.

    PGO dynamique tire parti de la compilation à plusieurs niveaux. Le JIT instrumenterait le code de niveau 0 pour savoir combien de fois la méthode est appelée, ou dans le cas des boucles, combien de fois la boucle s'exécute. Il peut également l'instrumenter pour d'autres choses. Par exemple, il peut suivre exactement quels types concrets sont utilisés comme cible d'une répartition d'interface, et ensuite, au niveau 1, spécialiser le code pour qu'il s'attende aux types les plus courants (c'est ce qu'on appelle la « dévirtualisation gardée » ou GDV). Vous pouvez voir cela dans ce petit exemple. Avec .NET 7, en donnant la valeur 1 à la variable d'environnement DOTNET_TieredPGO sur exemple ci-dessous,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Program
    {
        static void Main()
        {
            IPrinter printer = new Printer();
            for (int i = 0; ; i++)
            {
                DoWork(printer, i);
            }
        }
     
        static void DoWork(IPrinter printer, int i)
        {
            printer.PrintIfTrue(i == int.MaxValue);
        }
     
        interface IPrinter
        {
            void PrintIfTrue(bool condition);
        }
     
        class Printer : IPrinter
        {
            public void PrintIfTrue(bool condition)
            {
                if (condition) Console.WriteLine("Print!");
            }
        }
    }

    Avec PGO désactivé, nous obtenons le même débit de performance pour .NET 6 et .NET 7 :

    Nom : ration.jpg
Affichages : 2229
Taille : 15,6 Ko

    Mais le tableau change lorsque nous activons le PGO dynamique (DOTNET_TieredPGO=1). .NET 6 devient ~14% plus rapide, mais .NET 7 devient ~3x plus rapide !

    Nom : ration2.jpg
Affichages : 2234
Taille : 16,5 Ko

    dotnet/runtime#70377 est une autre amélioration précieuse de PGO dynamique, qui permet à PGO de jouer agréablement avec le clonage de boucle. Pour mieux comprendre cela, une brève digression sur ce que sont ces éléments. Le clonage de boucle est un mécanisme que le JIT utilise pour éviter diverses surcharges dans le chemin rapide d'une boucle. Considérons la méthode Test dans cet exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    using System.Runtime.CompilerServices;
     
    class Program
    {
        static void Main()
        {
            int[] array = new int[10_000_000];
            for (int i = 0; i < 1_000_000; i++)
            {
                Test(array);
            }
        }
     
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static bool Test(int[] array)
        {
            for (int i = 0; i < 0x12345; i++)
            {
                if (array[i] == 42)
                {
                    return true;
                }
            }
     
            return false;
        }
    }

    Le JIT ne sait pas si le tableau passé est suffisamment long pour que tous les accès à array[i] à l'intérieur de la boucle soient dans les limites, et il devrait donc injecter des contrôles de limites pour chaque accès. Alors qu'il serait agréable de simplement faire la vérification de la longueur en amont et de lancer une exception si la longueur n'est pas suffisante, cela pourrait également modifier le comportement (imaginez que la méthode écrive dans le tableau au fur et à mesure ou qu'elle modifie un état partagé). Au lieu de cela, le JIT utilise le « clonage de boucle ». Il réécrit essentiellement cette méthode Test pour qu'elle ressemble davantage à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    if (array is not null && array.Length >= 0x12345)
    {
        for (int i = 0; i < 0x12345; i++)
        {
            if (array[i] == 42) // no bounds checks emitted for this access :-)
            {
                return true;
            }
        }
    }
    else
    {
        for (int i = 0; i < 0x12345; i++)
        {
            if (array[i] == 42) // bounds checks emitted for this access :-(
            {
                return true;
            }
        }
    }
    return false;
    De cette façon, au prix d'une certaine duplication du code, on obtient une boucle rapide sans contrôle des limites et on ne paie que pour les contrôles des limites dans le chemin lent.

    Source : Microsoft

    Et vous ?

    Trouvez-vous pertinent l'analyse de Stephen Toub, sur les performances de .NET 7

    Partagez-vous l'avis selon lequel, .NET 7 est la version la plus rapide de tous les temps ?

    Quelle technologie utilisez-vous pour le développement d"applications ? Quelle appréciation faites vous de .NET 7 ?

    Quel aspect du framework vous intéresse le plus ? Sur quel point attendez-vous de voir des améliorations ?

    Voir aussi :

    .NET 6 apporterait jusqu'à 40 % de gain de vitesse par rapport .NET 5, les tests de mise en cache et de boucles serrées serraient jusqu'à 30 % plus rapide

    Microsoft annonce la disponibilité de .NET 6 Preview 4 qui apporte l'expérience Hot Reload, à Visual Studio et aux outils de ligne de commande

    Google Chrome et Microsoft Edge prendront en charge la fonction de sécurité CET d'Intel, pour maintenir la sécurité et prévenir des vulnérabilités

    Visual Studio 2022 Preview 4 est disponible et s'accompagne d'améliorations sur la productivité personnelle et d'équipe, le chargement à chaud dans ASP.NET Core et la gestion de thèmes

    Red Hat annonce un RHEL sans frais pour les petits environnements de production, notamment pour les charges de travail de production avec jusqu'à 16 serveurs de production
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    juin 2006
    Messages
    1 338
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : juin 2006
    Messages : 1 338
    Points : 1 364
    Points
    1 364
    Par défaut
    honnetement, je n'ai pas vu de différence flagrante entre .net 472 et .net core 3.1, et pas du tout entre .net core 3.1 et .net 6. Peut etre que mes applis ne sont pas vraiment représentatives des gains de perf....

  5. #5
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    mai 2019
    Messages
    1 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Rédacteur technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : mai 2019
    Messages : 1 016
    Points : 20 660
    Points
    20 660
    Par défaut Microsoft annonce la première version candidate de .NET 7
    Microsoft annonce la première version candidate de .NET 7
    testé avec Visual Studio 17.4 Preview 2

    Microsoft a publié en août .NET 7 Preview 7. L'entreprise a annoncé qu'il s'agit du dernier aperçu de .NET 7 et que la prochaine version sera la première release candidate (RC). Cet aperçu de .NET 7 comprenait des améliorations de System.LINQ, des permissions de fichiers Unix, des structures de bas niveau, de la génération de sources p/Invoke, de la génération de code et des websockets. Aujourd’hui, Jeremy Likness, Angelos Petropoulos, Jon Douglas, membres de l’équipe de .NET de Microsot ont annoncé .NET 7 Release Candidate 1.

    .NET 7 est le .NET le plus rapide à ce jour. Plus d'un millier d'améliorations ayant un impact sur les performances ont été apportées à .NET 7, notamment en ce qui concerne la réflexion, le remplacement des piles (OSR), le temps de démarrage, l'AOT natif, l'optimisation des boucles et de nombreux autres domaines.

    Nom : donet.png
Affichages : 1323
Taille : 1,3 Ko

    Lorsque le développement de .NET 7 a commencé, Microsoft a expliqué à la communauté que cette nouvelle version unifiera enfin tous les composants disparates des outils de développement .NET, permettant aux développeurs de créer tous les types d'applications - bureautiques, mobiles, Web et autres - sur la même bibliothèque de classes de base (BCL), le même moteur d'exécution et les mêmes compilateurs. C'était en fait l'objectif de .NET 5 - qui succède aux offres .NET Core - lorsqu'il a fait ses débuts en novembre 2020. Mais des problèmes de développement exacerbés par la pandémie n'ont pas permis d'atteindre cet objectif.

    En effet, tous les éléments prévus n'ont pas été intégrés à .NET 5 et ont été reportés jusqu'à l'arrivée de .NET 6 en novembre 2021 en tant que version LTS (Long Term Support). Mais même à ce moment-là, l'effort d'unification global de Microsoft était incomplet, car certains composants, tels que .NET Multi-platform App UI (.NET MAUI), n'ont pas respecté le calendrier. .NET MAUI a depuis atteint la disponibilité générale, et l'unification complète est désormais attendue pour novembre. Lors de la célébration des 20 ans de .NET en février dernier, Microsoft a réitéré son intention d'unifier tous les composants du framework à partir de .NET 7.

    .NET 7 Release Candidate 1 a été testé avec Visual Studio 17.4 Preview 2. Il est recommandé d'utiliser les builds du canal preview si vous voulez essayer .NET 7 avec les produits de la famille Visual Studio. Sous macOS, il est recommandé d'utiliser la dernière version de Visual Studio 2022 pour Mac.

    .NET Multi-platform App UI

    NET Multi-platform App UI (MAUI) unifie les API Android, iOS, macOS et Windows en une seule API afin que vous puissiez écrire une application qui fonctionne nativement sur plusieurs plateformes. .NET MAUI permet d'offrir les meilleures expériences d'application conçues spécifiquement pour chaque plateforme (Android, iOS, macOS, Windows et Tizen) tout en vous permettant de créer une expérience de marque cohérente grâce à un style et des graphiques riches. Chaque plateforme est prête à l'emploi et se comporte comme elle le devrait, sans widgets ni style supplémentaires.

    Nom : MAUIB.png
Affichages : 1116
Taille : 217,3 Ko

    L'objectif principal de .NET MAUI est de permettre aux utilisateurs d'offrir la meilleure expérience d'application telle qu'elle a été conçue spécialement pour chaque plateforme (Android, iOS, macOS, Windows et Tizen grâce à la collaboration avec Samsung), tout en permettant de créer des expériences de marque cohérentes grâce à un style et des graphiques riches.

    Dès le départ, chaque plateforme a l'apparence et le comportement qu'elle devrait avoir, sans qu'il soit nécessaire d'imiter des widgets ou des styles supplémentaires. Par exemple, .NET MAUI sur Windows est soutenu par WinUI 3, le premier composant d'interface utilisateur natif livré avec le SDK Windows App.

    Dans le cadre de .NET 7, .NET MAUI fournit un projet unique qui gère le ciblage multiple des appareils et de leurs plateformes. L'expérience Visual Studio permettant de tester .NET MAUI avec .NET 7 sera disponible dans la prochaine version 17.4 Preview 2.1.

    .NET MAUI fournit des API pour accéder aux services et aux fonctionnalités de chaque plateforme, tels que l'accéléromètre, les actions d'application, le système de fichiers, les notifications, et bien d'autres choses encore. Dans cet exemple, nous configurons des « actions d'application » qui ajoutent des options de menu à l'icône de l'application sur chaque plateforme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    AppActions.SetAsync(
        new AppAction("current_info", "Check Current Weather", icon: "current_info"),
        new AppAction("add_location", "Add a Location", icon: "add_location")
    );
    Optimisé pour la vitesse

    .NET MAUI est conçu pour les performances. Vous nous avez dit à quel point il est essentiel que vos applications démarrent le plus rapidement possible, notamment sur Android. Les contrôles d'interface utilisateur de .NET MAUI mettent en œuvre un modèle de gestionnaire-mappeur fin et découplé par rapport aux contrôles de la plate-forme native. Cela réduit le nombre de couches dans le rendu de l'interface utilisateur et simplifie la personnalisation des contrôles.

    Les mises en page de .NET MAUI ont été conçues pour utiliser un modèle de gestionnaire cohérent qui optimise les boucles de mesure et d'arrangement pour accélérer le rendu et la mise à jour de l'interface utilisateur. Microsoft a également mis en place des dispositions pré-optimisées pour des scénarios spécifiques tels que HorizontalStackLayout et VerticalStackLayout en plus de StackLayout.

    Avec pour objectif d'améliorer les performances au démarrage et de maintenir ou de réduire la taille des applications lors de la transition vers .NET 6. Microsoft obtient une amélioration de 34,9 % pour .NET MAUI et de 39,4 % pour .NET pour Android. Ces gains s'étendent également aux applications complexes ; l'application d'exemple .NET Podcast a démarré avec un temps de démarrage de 1299 ms, il est de 814,2 ms, soit une amélioration de 37,3 % depuis la preview 13.

    Cloud Native

    Les conteneurs sont devenus l'un des moyens les plus faciles de distribuer et d'exécuter un large éventail d'applications et de services dans le cloud. Le Runtime .NET a été renforcé pour les conteneurs il y a plusieurs années. Il est maintenant possible de créer des versions conteneurisées de vos applications avec seulement dotnet publish. Les images de conteneurs sont désormais un type de sortie pris en charge par le SDK .NET.

    Le cloud native est un ensemble de bonnes pratiques pour créer des applications pour et dans le cloud afin de profiter de la résilience, de l'évolutivité, de l'efficacité et de la rapidité. .NET peut être utilisé pour créer des applications natives pour le cloud.

    ARM64

    .NET aide à créer des applications qui fonctionnent sur les appareils ARM. L'équipe .NET a continué à améliorer les performances de .NET 7 pour Arm64. L'architecture du jeu d'instructions ou l'ISA de x64 et d'Arm64 est différente pour chacune d'entre elles et cette différence est toujours mise en évidence sous la forme de performance. Bien que cette différence existe entre les deux plateformes, essayons de comprendre les performances de .NET sur les plateformes Arm64 par rapport à x64. L’objectif de Microsoft dans .NET 7 n'était pas seulement d'atteindre la parité de performance entre x64 et Arm64, mais aussi de fournir des indications claires sur ce qu’on doit attendre lorsqu’on déplace les applications .NET de x64 à Arm64.

    Mise à l'échelle du pool de threads

    Une dégradation significative des performances sur les machines à plus grand nombre de cœurs (32+) a été constaté. Par exemple, sur les machines Ampère, les performances ont chuté de près de 80 %. En d'autres termes, le nombre de requêtes/secondes (RPS) était plus élevé sur 28 cœurs que sur 80 cœurs. Le problème sous-jacent était la façon dont les threads utilisaient et interrogeaient la « file d'attente globale » partagée.

    Lorsqu'un thread de travail avait besoin de plus de travail, il interrogeait la file d'attente globale pour voir s'il y avait plus de travail à faire. Sur les machines à fort nombre de cœurs, avec plus de threads impliqués, il y avait beaucoup de conflits lors de l'accès à la file d'attente globale. Plusieurs threads essayaient d'acquérir un verrou sur la file d'attente globale avant d'accéder à son contenu. Cela entraînait un blocage et donc une dégradation des performances.

    Le problème de mise à l'échelle du pool de threads n'est pas seulement limité aux machines Arm64 mais est vrai pour toutes les machines qui ont un nombre de cœurs plus élevé. Ce problème a été corrigé dans dotnet/runtime#69386 et dotnet/aspnetcore#42237 comme le montre le graphique ci-dessous. Bien que cela montre des améliorations significatives, nous pouvons remarquer que la performance n'évolue pas de façon linéaire avec plus de cœurs de machine.

    Nom : gpe.jpg
Affichages : 1080
Taille : 20,4 Ko

    Mise à l'échelle du pool de threads

    Une dégradation significative des performances sur les machines à plus grand nombre de cœurs (32+) a été constaté. Par exemple, sur les machines Ampère, les performances ont chuté de près de 80 %. En d'autres termes, le nombre de requêtes/secondes (RPS) était plus élevé sur 28 cœurs que sur 80 cœurs. Le problème sous-jacent était la façon dont les threads utilisaient et interrogeaient la « file d'attente globale » partagée.

    Lorsqu'un thread de travail avait besoin de plus de travail, il interrogeait la file d'attente globale pour voir s'il y avait plus de travail à faire. Sur les machines à fort nombre de cœurs, avec plus de threads impliqués, il y avait beaucoup de conflits lors de l'accès à la file d'attente globale. Plusieurs threads essayaient d'acquérir un verrou sur la file d'attente globale avant d'accéder à son contenu. Cela entraînait un blocage et donc une dégradation des performances.

    Le problème de mise à l'échelle du pool de threads n'est pas seulement limité aux machines Arm64 mais est vrai pour toutes les machines qui ont un nombre de cœurs plus élevé. Ce problème a été corrigé dans dotnet/runtime#69386 et dotnet/aspnetcore#42237 comme le montre le graphique ci-dessous. Bien que cela montre des améliorations significatives, nous pouvons remarquer que la performance n'évolue pas de façon linéaire avec plus de cœurs de machine.

    Source : Microsoft

    Et vous ?

    Quel est votre avis sur le sujet ?

    Voir aussi :

    Microsoft annonce la disponibilité de .NET 6 Preview 4 qui apporte l'expérience Hot Reload, à Visual Studio et aux outils de ligne de commande

    Google Chrome et Microsoft Edge prendront en charge la fonction de sécurité CET d'Intel, pour maintenir la sécurité et prévenir des vulnérabilités

    Visual Studio 2022 Preview 4 est disponible et s'accompagne d'améliorations sur la productivité personnelle et d'équipe, le chargement à chaud dans ASP.NET Core et la gestion de thèmes

    Red Hat annonce un RHEL sans frais pour les petits environnements de production, notamment pour les charges de travail de production avec jusqu'à 16 serveurs de production
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    novembre 2009
    Messages
    1 819
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : novembre 2009
    Messages : 1 819
    Points : 4 982
    Points
    4 982
    Par défaut
    Citation Envoyé par epsilon68 Voir le message
    honnetement, je n'ai pas vu de différence flagrante entre .net 472 et .net core 3.1, et pas du tout entre .net core 3.1 et .net 6. Peut etre que mes applis ne sont pas vraiment représentatives des gains de perf....
    Disons que tant que t'as pas de gros volume à traiter sur les scénarios en question personne ne verra la différence!

Discussions similaires

  1. Réponses: 2
    Dernier message: 13/05/2022, 14h22
  2. Réponses: 0
    Dernier message: 14/04/2022, 04h51
  3. Réponses: 0
    Dernier message: 18/06/2021, 14h42
  4. Réponses: 0
    Dernier message: 14/06/2018, 20h59
  5. Réponses: 0
    Dernier message: 20/02/2015, 10h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo