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 7 est maintenant disponible en tant que plateforme de développement unifiée de Microsoft


Sujet :

Dotnet

  1. #1
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    Mai 2019
    Messages
    1 844
    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 844
    Points : 36 271
    Points
    36 271
    Par défaut .NET 7 est maintenant disponible en tant que plateforme de développement unifiée de Microsoft
    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 : 32899
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
    3 160
    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 : 3 160
    Points : 66 256
    Points
    66 256
    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 : 31993
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 844
    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 844
    Points : 36 271
    Points
    36 271
    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 : 22029
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 : 3987
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 : 3892
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 : 3900
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 : 3896
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 354
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Points : 1 419
    Points
    1 419
    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 844
    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 844
    Points : 36 271
    Points
    36 271
    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 : 8103
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 : 2090
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 : 2057
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
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    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!

  7. #7
    Chroniqueur Actualités

    Homme Profil pro
    Dirigeant
    Inscrit en
    Juin 2016
    Messages
    3 160
    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 : 3 160
    Points : 66 256
    Points
    66 256
    Par défaut .NET 7 est maintenant disponible en tant que plateforme de développement unifiée de Microsoft
    .NET 7 est maintenant disponible en tant que plateforme de développement unifiée de Microsoft
    et apporte des améliorations pour .NET MAUI et le support de .NET pour ARM64

    La version stable de .NET 7 a été officiellement publiée mardi, jour d'ouverture de l'événement en ligne .NET Conf, en tant que sa plateforme de développement multiplateforme open source de Microsoft. La firme de Redmond affirme qu'avec .NET 7, vous n'apprenez qu'une fois et réutilisez vos compétences avec un seul SDK, un seul Runtime, un seul ensemble de bibliothèques de base pour construire de nombreux types d'applications (Cloud, Web, Desktop, Mobile, Gaming, IoT et AI). Microsoft a également publié mardi la version stable de Visual Studio 2022 17.4.

    .NET 7 fait enfin ce que .NET 5 était censé faire en 2020 : couronner les efforts déployés par Microsoft depuis des années pour unifier des produits de développement disparates avec "un seul .NET à l'avenir". Microsoft estime que les mots clés de cette version sont "unifié", "moderne" et "simple". Le terme "unifié" signifie que .NET 7 est basé sur une seule bibliothèque de classes de base (Base Class Library - BCL). Toutefois, cela ne signifie pas que les fonctions spécifiques à la plateforme ne sont pas disponibles, et les API spécifiques au système d'exploitation sont accessibles en spécifiant le moniker de trame cible (TFM) suivant.

    En matière de "modernité", .NET MAUI, une bibliothèque d'interface utilisateur multiplateforme, fait désormais partie de .NET 7. .NET 7 est conçu pour les applications natives modernes, les clients mobiles, les services périphériques et les technologies de bureau. Créez des expériences mobiles à l'aide d'une base de code unique sans compromettre les performances natives grâce à .NET MAUI. Créez des applications à page unique (SPA) réactives qui s'exécutent dans votre navigateur et hors ligne en tant qu'applications Web progressives (PWA) à l'aide de technologies familières comme C# et les modèles Razor.

    Nom : 0.png
Affichages : 21213
Taille : 45,8 Ko

    Ces expériences modernes plus rapides ne sont pas uniquement destinées aux nouvelles applications. L'assistant de mise à niveau .NET vous fournira des informations sur la compatibilité et, dans certains cas, assurera la migration complète de vos applications vers .NET 6 et .NET 7. Quant au mot "simple", Microsoft a mentionné des améliorations du langage : la BCL a introduit une interface générique liée aux mathématiques qui permet d'effectuer des opérations mathématiques de manière générique, c'est-à-dire indépendamment du type exact. Il n'est pas nécessaire de surcharger les méthodes pour chaque type.

    « .NET 7 apporte à vos applications des performances accrues et de nouvelles fonctionnalités pour C# 11/F# 7, .NET MAUI, ASP.NET Core/Blazor, les API Web, WinForms, WPF, etc. Avec .NET 7, vous pouvez aussi facilement conteneuriser vos projets .NET 7, mettre en place des flux de travail CI/CD dans les actions GitHub et obtenir une observabilité cloud-native », ont écrit Jon Douglas, Jeremy Likness et Angelos Petropoulos dans un billet de blogue mardi.

    Cibler .NET 7

    Lorsque vous ciblez un framework dans une application ou une bibliothèque, vous spécifiez l'ensemble des API que vous souhaitez rendre disponibles. Pour cibler .NET 7, il suffit de modifier le framework cible dans votre projet.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <TargetFramework>net7.0</TargetFramework>

    Les applications qui ciblent le moniker de framework cible net7.0 (TFM) fonctionneront sur tous les systèmes d'exploitation et architectures de CPU pris en charge. Elles vous donnent accès à toutes les API de .NET 7 ainsi qu'à un grand nombre d'API spécifiques au système d'exploitation, telles que :

    • net7.0-android ;
    • net7.0-ios ;
    • net7.0-maccatalyst ;
    • net7.0-macos ;
    • net7.0-tvos ;
    • net7.0-windows.


    ARM64

    L'industrie s'est orientée vers les processeurs ARM, tout comme .NET. L'un des principaux avantages des processeurs ARM est l'efficacité énergétique. Cela permet d'obtenir les meilleures performances avec la plus faible consommation d'énergie. Autrement dit, vous pouvez faire plus avec moins. Dans .NET 5, Microsoft a décrit les initiatives qu'il a prises en matière de performances pour ARM64. Aujourd'hui, deux versions plus tard, l'entreprise partage le chemin parcouru. Son objectif permanent est d'atteindre la parité de performances entre x64 et ARM64 afin d'aider les clients à transférer leurs applications .NET vers ARM.

    Améliorations du temps d'exécution

    Selon Microsoft, l'une des difficultés rencontrées lors des recherches sur x64 et ARM64 a été de découvrir que la taille du cache L3 n'était pas correctement lue sur les machines ARM64. L'équipe a modifié l'heuristique pour renvoyer une taille approximative si la taille du cache L3 ne pouvait pas être récupérée à partir du système d'exploitation ou du BIOS de la machine. Elle peut maintenant mieux évaluer le nombre de cœurs par taille de cache L3. Ensuite, elle a compris l'atomique de LSE. Ce qui, si vous n'êtes pas familier, fournit des API atomiques pour obtenir un accès exclusif aux régions critiques.

    Nom : 1.png
Affichages : 5455
Taille : 6,1 Ko

    Sur les machines x86-x64 à architecture CISC, les opérations de lecture-modification-écriture (RMW) sur la mémoire peuvent être effectuées par une seule instruction en ajoutant un préfixe de verrouillage. Cependant, sur les machines à architecture RISC, les opérations RMW ne sont pas autorisées et toutes les opérations sont effectuées par le biais de registres. Par conséquent, pour les scénarios de concurrence, ils ont une paire d'instructions. L'instruction "Load Acquire" (ldaxr) permet d'obtenir un accès exclusif à la région de mémoire de telle sorte qu'aucun autre cœur ne puisse y accéder et l'instruction "Store Release" (stlxr) libère l'accès pour les autres cœurs.

    Entre ces paires, les opérations critiques sont effectuées. Si l'opération stlxr a échoué parce qu'un autre processeur a opéré sur la mémoire après avoir chargé le contenu à l'aide de ldaxr, il existe un code pour réessayer (cbnz saute en arrière pour réessayer) l'opération. ARM a introduit les instructions atomiques LSE dans la version 8.1. Avec ces instructions, de telles opérations peuvent être effectuées en moins de code et plus rapidement que la version traditionnelle. Lorsque l'équipe a activé cette fonction pour Linux, puis l'a étendue à Windows, elle a constaté un gain de performance d'environ 45 %.

    Améliorations des bibliothèques

    Pour optimiser les bibliothèques qui utilisent des intrinsèques, l'équipe a ajouté de nouvelles aides multiplateformes. Il s'agit notamment d'aides pour Vector64, Vector128 et Vector256. Les aides multiplateformes permettent d'unifier les algorithmes de vectorisation en remplaçant les intrinsèques spécifiques au matériel par des intrinsèques agnostiques au matériel. Cela profitera aux utilisateurs de toutes les plateformes, mais l'équipe s'attend à ce que la plateforme ARM64 en bénéficie le plus, car les développeurs sans expertise ARM64 pourront toujours utiliser les aides pour tirer parti des intrinsèques du matériel Arm64.

    Nom : 2.png
Affichages : 5456
Taille : 61,0 Ko

    La réécriture d'API telles que EncodeToUtf8 et DecodeFromUtf8 d'une implémentation SSE3 à une implémentation vectorielle peut apporter jusqu'à 60 % d'amélioration. De même, la conversion d'autres API, telles que NarrowUtf16ToAscii() et GetIndexOfFirstNonAsciiChar(), permet de gagner jusqu'à 35 % en performances.

    Impact sur les performances

    Grâce au travail de l'équipe sur .NET 7, de nombreux microbenchmarks se sont améliorés de 10 à 60 %. Au début de .NET 7, les requêtes par seconde (RPS) étaient plus faibles pour ARM64, mais ont lentement dépassé la parité de x64. De même, pour la latence (mesurée en millisecondes), l'équipe a dépassé la parité avec x64.

    Prise en charge améliorée de .NET sous Linux

    .NET 6 est inclus dans Ubuntu 22.04 (Jammy) et peut être installé avec la commande apt install dotnet6. En outre, il existe une image de conteneur optimisée, préconstruite et très petite qui peut être utilisée telle quelle.

    Prise en charge d'IBM Power 64 bits

    Outre l'architecture x64 (Intel/AMD 64 bits), ARM64 (ARM 64 bits) et s390x (IBM Z 64 bits), .NET est désormais également disponible pour l'architecture ppc64le (IBM Power 64 bits) ciblant RHEL 8.7 et RHEL 9.1. Grâce à la disponibilité de l'exécution native sur Power, les plus de 25 000 clients d'IBM Power peuvent consolider les applications .NET existantes sur Windows x86 pour les exécuter sur la même plateforme Power que leurs applications et bases de données professionnelles IBM i et AIX.

    Ce faisant, ils peuvent améliorer considérablement le développement durable en réduisant jusqu'à 5 fois leur empreinte carbone, tout en bénéficiant d'une mise à l'échelle sur site de la capacité de RHEL (Red Hat Enterprise Linux) et d'OpenShift, et en assurant la sécurité des transactions et des données de bout en bout de l'entreprise.

    Blazor

    Blazor continue d'évoluer et .NET 7 comprend de nombreuses améliorations majeures. Blazor prend désormais en charge la gestion des événements de changement de lieu, améliore l'expérience de débogage WebAssembly et prend en charge l'authentification par OpenID Connect.

    Assistant de mise à niveau

    L'assistant de mise à niveau .NET fournit des conseils, des informations et une automatisation étape par étape pour faire passer vos anciennes applications à .NET 6 et .NET 7. Dans certains cas, il peut effectuer la migration pour vous. Il permet de réduire le temps et la complexité lors de la modernisation d'anciennes bases de code. Par exemple, apprenez comment faire passer vos applications WCF à .NET Core avec l'aide de CoreWCF. Avec .NET 7, les expériences améliorées comprennent :

    • ASP.NET vers ASP.NET Core :
      • adaptateurs System.Web (aperçu) ;
      • migrations incrémentielles (aperçu) ;
    • Ajout d'un plus grand nombre d'analyseurs et de correcteurs de code pour WinForms, WPF et les bibliothèques console/classe ;
    • La possibilité d'analyser les binaires ;
    • Prise en charge de UWP vers Windows App SDK et WinUI.


    .NET pour les applications natives du cloud

    Avec .NET 7, il est plus facile que jamais de créer des applications natives du cloud. Utilisez les services connectés de Visual Studio pour vous connecter en toute sécurité à un service de données et chiffrer vos chaînes de connexion dans un fichier de secrets d'utilisateur ou dans Azure Key Vault. Créez votre application directement dans une image de conteneur. Utilisez Entity Framework 7 pour écrire des requêtes LINQ (Language Integrated Query) fortement typées qui utilisent le support JSON de SQL Server pour extraire rapidement le contenu des documents JSON stockés dans votre base de données relationnelle.

    Livrez des documents JSON sécurisés via des points de terminaison authentifiés en utilisant seulement quelques lignes de code avec l'expérience Minimal APIs. Obtenez des informations sur votre application en cours d'exécution avec Open Telemetry.

    Prise en charge d'Azure

    Non seulement .NET 7 est idéal pour créer des applications natives du cloud, mais les services PaaS d'Azure tels que App Service pour Windows et Linux, Static Web Apps, Azure Functions et Azure Container Apps sont prêts pour .NET 7. Tout au long de la première semaine de la sortie, il se peut que les temps de démarrage des applications .NET 7 soient légèrement plus longs, car le SDK .NET 7 sera installé juste à temps pour les clients qui créent de nouveaux App Services utilisant .NET 7. De même, si vous exécutez une version préliminaire de .NET 7, il vous suffit de redémarrer votre App Service pour passer aux bits GA.

    Prise en charge intégrée des conteneurs

    La popularité et l'utilisation pratique des conteneurs sont en hausse, et pour de nombreuses entreprises, ils représentent le moyen privilégié de déployer vers le cloud. Cependant, l'utilisation de conteneurs ajoute de nouvelles tâches au carnet de commandes d'une équipe, notamment la création et la publication d'images, le contrôle de la sécurité et de la conformité, et l'optimisation des performances des images. L'équipe pense qu'il est possible de créer une expérience meilleure et plus rationnelle avec les conteneurs .NET. Vous pouvez désormais créer des versions conteneurisées de vos applications avec seulement dotnet publish.

    « Nous avons conçu cette solution dans le but de l'intégrer de manière transparente à la logique de construction existante, en tirant parti de nos propres outils C# et des performances d'exécution, et en l'intégrant directement dans le SDK .NET pour des mises à jour régulières », explique l'équipe.

    Microsoft Orleans

    Microsoft Orleans 7.0 offrira un modèle de programmation plus simple avec des Grains "plain old CLR object" (POCO), offrira des performances jusqu'à 150 % supérieures à celles de la version 3.x et introduira de nouvelles améliorations en matière de sérialisation et d'immuabilité. Les développeurs ASP.NET Core peuvent ajouter de l'état distribué avec simplicité en utilisant Orleans, et être sûrs que leurs applications évolueront horizontalement sans ajouter de complexité.

    « Nous continuerons à investir pour rapprocher les fonctionnalités d'Orleans de la pile ASP.NET afin de garantir que vos applications Web et API sont prêtes à évoluer dans le nuage, dans des scénarios d'hébergement distribué ou même dans des déploiements multiclouds », a déclaré l'équipe.

    Avec la prise en charge des mécanismes de stockage et des bases de données les plus courants et la possibilité de s'exécuter partout où ASP.NET Core peut s'exécuter, Orleans est un excellent choix pour doter vos applications .NET de capacités distribuées et natives du cloud sans avoir à apprendre un nouveau cadre ou un nouvel ensemble d'outils.

    C# 11 et F# 7

    Les plus récents ajouts aux langages C# et F# sont C# 11 et F# 7. C# 11 rend possible de nouvelles fonctionnalités telles que les mathématiques génériques tout en simplifiant votre code grâce à des améliorations de l'initialisation des objets, des chaînes de caractères brutes, et bien plus encore.

    Bibliothèques .NET

    .NET 7 a apporté des améliorations significatives à de nombreuses bibliothèques de premier plan de .NET. Vous y trouverez, entre autres, la prise en charge des annotations nullable pour les paquets Microsoft.Extensions.*, la personnalisation des contrats et les hiérarchies de types pour System.Text.Json, ainsi que de nouvelles API Tar pour vous aider à écrire des données au format TAR (Tape Archive).

    SDK .NET

    Le SDK .NET continue d'ajouter de nouvelles fonctionnalités pour vous rendre plus productif que jamais. Dans .NET 7, l'équipe améliore vos expériences avec la CLI .NET, la création de modèles et la gestion de vos paquets dans un emplacement central.

    Performances

    Les performances sont un élément important de chaque version de .NET. Chaque année, l'équipe .NET publie un blogue sur les dernières améliorations. Voici un court extrait du dernier billet sur les performances :

    « .NET 7 est rapide. Vraiment rapide. Un millier de PR 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. Si votre responsable vous demande pourquoi votre projet devrait passer à .NET 7, vous pouvez répondre : "en plus de toutes les nouvelles fonctionnalités de la version, .NET 7 est super rapide" », a écrit Stephen Toub de Microsoft.

    Support de .NET 7

    .NET 7 est officiellement pris en charge par Microsoft. Il s'agit d'une version STS (Standard Term Support) qui sera supportée pendant 18 mois. Les versions impaires de .NET sont des versions STS qui bénéficient d'un support et de correctifs gratuits pendant six mois après une version STS ou LTS ultérieure.

    Source : Microsoft

    Et vous ?

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

    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 première version candidate de .NET 7, testé avec Visual Studio 17.4 Preview 2

    Microsoft a annoncé la disponibilité générale de .NET 5 qui inclut C# 9, F# 5 et une prise en charge native de Windows Arm64

    Microsoft annonce qu'il a apporté quelques améliorations importantes à Visual Studio 2019 16.8, afin de faciliter la migration de projets d'envergure de .NET Framework vers .NET 5
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  8. #8
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    794
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 794
    Points : 987
    Points
    987
    Par défaut

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 12
    Points : 70
    Points
    70
    Par défaut MAUI et webAssembly
    Et toujours pas d'exécution d'appli MAUI en WebAssembly? non? Dommage, je reste donc à développer mon IHM en Uno alors...
    MAUI universel? mon oeil...

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