Partager via


Composants Windows Runtime et optimisation de l’interopérabilité

Créez des applications Windows Runtime qui utilisent des composants Windows et l’interopérabilité entre les types natifs et managés, tout en évitant les problèmes de performance d’interopérabilité.

Bonnes pratiques pour l’interopérabilité avec les composants Windows Runtime

Si vous n’y faites pas attention, l’utilisation de composants Windows Runtime peut avoir un gros impact sur les performances de votre application. Cette section explique comment obtenir des performances optimales quand votre application utilise des composants Windows Runtime.

Introduction

L’interopérabilité peut avoir un impact important sur les performances et il peut arriver que vous y ayez recours sans vous en apercevoir. Windows Runtime traite automatiquement une grande part de l’interopérabilité avec ses composants pour que vous soyez plus productif et réutilisiez tout code écrit dans un autre langage. Nous vous recommandons de tirer parti de ce que Windows Runtime fait à votre place, mais sachez que cela peut avoir un impact sur les performances. Cette section indique ce que vous pouvez faire pour atténuer l’impact de l’interopérabilité sur les performances de votre application.

Windows Runtime a une bibliothèque de types accessible à partir de tout langage permettant d’écrire une application de plateforme Windows universelle. Vous pouvez utiliser les types Windows Runtime en C# ou Microsoft Visual Basic de la même manière que vous utilisez des objets .NET. Vous n’avez pas besoin de configurer la plateforme de sorte qu’elle invoque des appels de méthode pour accéder aux composants Windows Runtime. Cela rend l’écriture des applications beaucoup moins complexe mais sachez que l’interopérabilité peut être plus importante que prévu. Si un composant Windows Runtime est écrit dans un langage autre que C# ou Visual Basic, vous dépassez les limites de l’interopérabilité lorsque vous utilisez ce composant. Cela a un impact sur les performances d’une application.

Quand vous développez une application de plateforme Windows Universelle en C# ou Visual Basic, les deux types d’API les plus courants que vous utilisez sont les API Windows Runtime et les API .NET pour les applications UWP. En général, les types fournis par Windows sont basés sur Windows Runtime dans les espaces de noms qui commencent par « Windows » et les types .NET se trouvent dans des espaces de noms qui commencent par « System ». Il existe toutefois des exceptions. Les types dans .NET pour les applications UWP ne nécessitent pas d’interopérabilité quand ils sont utilisés. Si vous constatez de mauvaises performances pour des actions qui utilisent Windows Runtime, vous pouvez peut-être utiliser .NET pour les applications UWP à la place afin d’obtenir de meilleures performances.

Remarque La plupart des composants Windows Runtime fournis avec Windows 10 étant implémentés en C++, vous dépassez les limites de l’interopérabilité lorsque vous les utilisez en C# ou Visual Basic. Comme toujours, observez le comportement de votre application pour déterminer si l’utilisation de composants Windows Runtime nuit à ses performances avant de modifier le code.

Dans cette rubrique, l’expression « composants Windows Runtime » désigne les composants Windows Runtime écrits dans un langage autre que C# ou Visual Basic.

 

Chaque fois que vous accédez à une propriété ou appelez une méthode sur un composant Windows Runtime, cela induit un coût d’interopérabilité. En fait, créer un composant Windows Runtime est plus coûteux en ressources que de créer un objet .NET. C’est parce que Windows Runtime doit exécuter du code qui est converti du langage de votre application à celui du composant. En outre, si vous transmettez des données au composant, ces données doivent être converties du type géré au type non géré.

Utilisation des composants Windows Runtime avec efficacité

Si vous souhaitez obtenir de meilleures performances, vous pouvez faire en sorte que votre code utilise les composants Windows Runtime le plus efficacement possible. Cette section décrit quelques conseils pour améliorer les performances lorsque vous utilisez des composants Windows Runtime.

Un nombre d’appels important dans une courte période est nécessaire pour que l’impact sur les performances soit visible. Une application bien conçue qui encapsule les appels aux composants Windows Runtime à partir de la logique métier et de tout autre code managé ne doit pas induire de coûts excessifs d’interopérabilité. Toutefois, si vos tests indiquent que l’utilisation des composants Windows Runtime nuit aux performances de votre application, les conseils présentés dans cette section vous aideront à éviter ce problème.

Utiliser des types fournis par .NET pour les applications UWP

Dans certains cas, vous pouvez accomplir une tâche en utilisant un type Windows Runtime ou un type fourni par .NET pour les applications UWP. Nous vous conseillons de ne pas essayer de mélanger les types .NET et les types Windows Runtime. Essayez de n’utiliser qu’un seul type. Par exemple, vous pouvez analyser un flux de code xml à l’aide du type Windows.Data.Xml.Dom.XmlDocument (type Windows Runtime) ou du type System.Xml.XmlReader (type .NET). Utilisez l’API de la même technologie que celle du flux. Par exemple, si vous lisez des données xml à partir d’un type MemoryStream, utilisez le type System.Xml.XmlReader, car les deux types sont des types .NET. Si vous lisez des données à partir d’un fichier, utilisez le type Windows.Data.Xml.Dom.XmlDocument, car les API de fichier et XmlDocument sont tous les deux implémentés dans des composants Windows Runtime natifs.

Copier les objets Window Runtime dans les types .NET

Quand un composant Windows Runtime retourne un objet Windows Runtime, il peut être judicieux de copier l’objet retourné dans un objet .NET. Cela est notamment important lorsque vous utilisez des collections et des flux.

Si vous appelez une API Windows Runtime qui retourne une collection, puis que vous enregistrez cette collection et y accédez de nombreuses fois, il peut être utile de copier la collection dans une collection .NET et d’utiliser ensuite cette collection .NET.

Mettre en cache les résultats des appels aux composants Windows Runtime pour un usage ultérieur

Vous obtiendrez probablement de meilleures performances en enregistrant les valeurs dans des variables locales au lieu d’accéder à un type Windows Runtime plusieurs fois. Cela peut s’avérer particulièrement utile si vous utilisez une valeur dans une boucle. Observez le comportement de votre application pour déterminer si l’utilisation de variables locales améliore ses performances. L’utilisation de valeurs mises en cache peut augmenter la vitesse de votre application, car elle consacre moins de temps à l’interopérabilité.

Combiner des appels avec des composants Windows Runtime

Essayez d’accomplir des tâches avec le moins d’appels possible aux objets UWP. Par exemple, il est en général préférable de lire un grand volume de données à partir d’un flux que de lire de petites quantités de données les unes après les autres.

Utilisez des API qui permettent de réaliser une tâche avec le moins d’appels possible au lieu d’utiliser des API qui permettent de réaliser moins de travail avec plus d’appels. Par exemple, créez de préférence un objet en appelant des constructeurs qui initialisent plusieurs propriétés à la fois au lieu d’appeler le constructeur par défaut et de lui affecter des propriétés une par une.

Création d’un composant Windows Runtime

Si vous écrivez un composant Windows Runtime pouvant être utilisé par des applications écrites en C++ ou JavaScript, assurez-vous que ce composant est conçu pour de bonnes performances. Toutes les suggestions pour obtenir des performances optimales dans les applications s’appliquent également aux composants. Observez votre composant afin de savoir quelles API connaissent un trafic élevé et en conséquence, envisagez de fournir des API qui permettent à vos utilisateurs de faire leur travail en quelques appels.

Préserver la rapidité de votre application en cas d’utilisation de l’interopérabilité en code managé

Windows Runtime facilite l’interopérabilité entre les codes natif et managé mais, si vous ne faites pas attention, cela peut occasionner des coûts de performance. Nous expliquons ici comment obtenir des performances optimales lorsque vous utilisez l’interopérabilité dans vos applications UWP managées.

Avec Windows Runtime, les développeurs peuvent choisir le langage dans lequel ils souhaitent écrire leurs applications UWP en XAML, grâce aux projections des API Windows Runtime disponibles dans chaque langage. Dans le cas d’une application en C# ou Visual Basic, cette interopérabilité a un coût. En effet, comme les API Windows Runtime sont habituellement implémentées en code natif, chaque appel de Windows Runtime depuis C# ou Visual Basic nécessite que le CLR passe d’un frame de pile managé à un frame de pile natif, et qu’il marshale les paramètres de fonction aux représentations accessibles par le code natif. Ce temps de traitement supplémentaire a un impact négligeable pour la plupart des applications. Toutefois, si vous effectuez beaucoup d’appels (des centaines de milliers à des millions) aux API Windows Runtime dans le chemin critique d’une application, ce coût peut devenir considérable. En général, il faut veiller à ce que le temps consacré à la transition entre les langages est faible par rapport à l’exécution du reste de votre code. Ceci est illustré par le schéma suivant.

Les transitions d’interopérabilité ne doivent pas dominer la durée d’exécution du programme.

Les types répertoriés dans .NET for Windows apps ne présentent pas ce coût d’interopérabilité lorsqu’ils sont utilisés en C# ou Visual Basic. En règle générale, vous pouvez supposer que les types dans les espaces de noms qui commencent par « Windows. » font partie de l’ensemble d’API Windows Runtime fourni par Windows, tandis que les types dans les espaces de noms qui commencent par « System ». sont des types .NET. Gardez en tête qu’une utilisation même simple des types Windows Runtime a un coût d’interopérabilité pour l’allocation ou l’accès aux propriétés.

Vous devez effectuer des mesures sur votre application et déterminer si l’interopérabilité requiert une partie significative de la durée d’exécution de votre application avant d’optimiser les coûts liés à l’interopérabilité. Lors de l’analyse de votre application avec Visual Studio, il est très facile d’obtenir une limite supérieure des coûts d’interopérabilité en utilisant la vue Fonctions et en regardant le temps consacré aux méthodes qui appellent Windows Runtime.

Si votre application est lente à cause de la surcharge liée à l’interopérabilité, vous pouvez améliorer ses performances en diminuant le nombre d’appels aux API Windows Runtime sur les chemins de code réactifs. Par exemple, lorsqu’un moteur de jeu doit effectuer une multitude de calculs physiques en demandant constamment la position et les dimensions de UIElements, il peut le faire beaucoup plus rapidement en stockant les informations nécessaires de UIElements dans des variables locales. De cette manière, il effectue les calculs sur ces valeurs mises en cache, puis retourne le résultat final à UIElements une fois les calculs terminés. Prenons un autre exemple : lorsqu’une collection est souvent sollicitée par du code C# ou Visual Basic, il est plus judicieux d’utiliser une collection de l’espace de noms System.Collections qu’une collection de l’espace de noms Windows.Foundation.Collections. Vous pourriez également combiner des appels aux composants Windows Runtime. Cela est par exemple possible lors de l’utilisation des API Windows.Storage.BulkAccess.

Création d’un composant UWP

Si vous écrivez un composant Windows Runtime pour des applications écrites en C++ ou JavaScript, assurez-vous que ce composant est conçu pour de bonnes performances. Votre surface d’API définit votre limite d’interopérabilité ainsi que le degré auquel vos utilisateurs devront prendre en compte les recommandations de cette rubrique. Si vous distribuez vos composants à des tierces parties, ceci revêt une importance toute particulière.

Toutes les suggestions pour obtenir des performances optimales dans les applications s’appliquent également aux composants. Observez votre composant afin de savoir quelles API connaissent un trafic élevé et fournissez des API qui permettent à vos utilisateurs de faire leur travail en quelques appels. Des efforts significatifs ont été consacrés à la conception de Windows Runtime en vue de permettre aux applications de l’utiliser sans avoir à dépasser fréquemment la limite d’interopérabilité.