Optimiser les performances d'une API .Net Core

December 20, 2019 .Net Core 2 minutes, 33 secondes

Présentation d'astuces et techniques pour optimiser les performances d'une API .Net Core.

Le développement

Gestion asynchrone

Eviter les appels pouvant provoquer un blocage comme cela peut se produire avec des appels synchrones. Ne jamais utiliser par exemple Task.Wait ou Task.Result qui va bloquer l'appel asynchrone.

Il faut s'assurer que les appels d'accès aux données et les appels long sont gérer de manière asynchrone (async/await).

Gestion mémoire

Eviter de stocker des objets volumineux au niveau de l'API, le garbage collector en .NET Core est connu pour être moins efficace sur les objets volumineux >85Ko. Dans le cas d'une API devant gérer des objets volumineux, il faut étudier l'intégration d'un cache.

L'outil PerfView peut être utillisé pour analyser les allocations mémoire de votre API.

Gestion des données

Optimiser tous les appels vers les données que ce soit au niveau de la lecture ou l'écriture des données. Attention à l'utilisation de Linq avec l'Entity Framework afin d'éviter les requêtes multiples inutiles. A chaque appel d'une requête acec ToList par exemple génère une requête directement sur la base de données. Eviter de charger des lots complets de données qui ne sont potentiellement inutile pour vos applications.

Optimisation possible sur la lecture seule :

var users = dbContext.Users.where(x => x.firstname = 'yves').AsNoTracking().ToList ();

Maximiser le chargement des données associées :

Entity Framework prend en charge trois méthodes de chargement des données associées : le chargement hâtif, le chargement différé et le chargement explicite. Les techniques présentées dans cette rubrique s’appliquent également aux modèles créés avec Code First et EF Designer.

https://docs.microsoft.com/fr-fr/ef/ef6/querying/related-data?redirectedfrom=MSDN

Autre astuce : désactiver l'auto-détection de changement Vous pouvez désactiver le AutoDetectChangesEnabled avant d'ajouter, puis il faut le rallumer après.

using ( var  context  =  new  EFContext ()) {
    var  preAutoDetectChangesEnabled = context.Configuration.AutoDetectChangesEnabled;
    context.Configuration.AutoDetectChangesEnabled = false ;
    // Effectuer des ajouts
    context.SaveChanges();
    context.Configuration.AutoDetectChangesEnabled  =  preAutoDetectChangesEnabled ;
}

Exemple d'une requête Linq plus complexe


public async Task < PaginatedList < Post >> GetPagedPendingPosts
     (int pageIndex, int pageSize, List<Category> allowedCategories)
{
  var allowedCatIds = allowedCategories.Select(x => x.Id);
  var query = _context.Post
    .Include(x => x.Topic.Category)
    .Include(x => x.User)
    .Where(x => x.Pending == true && allowedCatIds.Contains(x.Topic.Category.Id))
    .OrderBy(x => x.DateCreated);

  return await PaginatedList<Post>.CreateAsync(query.AsNoTracking(), pageIndex, pageSize);
}

Thread blocking code

Afin de détecter plus facilement du code lent ou une occupation importante du pool de thread, vous pouvez tester la librairie Ben.BlockingDetector. Cette librairie peut être installée via un package nuget.

public void configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.useBlockingDetection
}

Activer la compression GZip si necessaire

La compression GZip permet de réduire la taille des réponses tel que décrit ci-dessous.

public void ConfigureServices(IServiceCollection services)
{
  services.AddResponseCompression();

  services.Configure<GzipCompressionProviderOptions>(options => {
    options.Level = CompressionLevel.Fastest;
  });
}

Outillages

  1. LINKPad : pour ecrire les requêtes SQL de type Linq
  2. SQL Profiler : permet voir le parcours d'execution des requêtes Linq
  3. Telerik JustTrace, DotTrace, ANTS Performance Profiler : outil de profilage de code
  4. PerfView peut être utillisé pour analyser les allocations mémoire de votre API.

Liens

Meilleures pratiques en matière de performances de ASP.NET Core : https://docs.microsoft.com/fr-fr/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1

Response caching in ASP.NET Core https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-2.2

Performances d'Entity Framework et ce que vous pouvez faire à ce sujet https://www.red-gate.com/simple-talk/dotnet/net-tools/entity-framework-performance-and-what-you-can-do-about-it/

alt