ASP.NET Core Performance : 20 techniques d'optimisation avancées

Optimisez vos applications ASP.NET Core avec ces techniques avancées : caching, compression, pooling et profiling.

Olivier Dupuy
04 juin 2025

3886

Vues

0

Commentaires

25

Min de lecture
ASP.NET Core Performance : 20 techniques d'optimisation avancées

Performance ASP.NET Core : L'art de l'optimisation

La performance d'une application web peut faire la différence entre le succès et l'échec. Voici 20 techniques avancées pour optimiser vos applications ASP.NET Core.

1. Object Pooling

Réutilisez les objets coûteux à créer :


// Configuration du pooling
services.AddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
    var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
    var policy = new StringBuilderPooledObjectPolicy();
    return provider.Create(policy);
});

// Utilisation dans un controller
public class HomeController : Controller
{
    private readonly ObjectPool<StringBuilder> _stringBuilderPool;
    
    public HomeController(ObjectPool<StringBuilder> stringBuilderPool)
    {
        _stringBuilderPool = stringBuilderPool;
    }
    
    public IActionResult GenerateReport()
    {
        var sb = _stringBuilderPool.Get();
        try
        {
            sb.AppendLine("Report Header");
            sb.AppendLine($"Generated: {DateTime.Now}");
            return Content(sb.ToString());
        }
        finally
        {
            _stringBuilderPool.Return(sb);
        }
    }
}

2. Memory Caching Avancé


public class CachedUserService
{
    private readonly IMemoryCache _cache;
    private readonly IUserRepository _userRepository;
    
    public async Task<User> GetUserAsync(int userId)
    {
        return await _cache.GetOrCreateAsync($"user_{userId}", async entry =>
        {
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30);
            entry.SlidingExpiration = TimeSpan.FromMinutes(5);
            entry.Priority = CacheItemPriority.High;
            
            // Invalidation conditionnelle
            entry.RegisterPostEvictionCallback((key, value, reason, state) =>
            {
                if (reason == EvictionReason.Expired)
                {
                    // Log ou notification
                    Console.WriteLine($"Cache expired for {key}");
                }
            });
            
            return await _userRepository.GetByIdAsync(userId);
        });
    }
}

3. Response Compression Intelligente


// Startup.cs
services.AddResponseCompression(options =>
{
    options.Providers.Add<BrotliCompressionProvider>();
    options.Providers.Add<GzipCompressionProvider>();
    options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
    {
        "application/json",
        "text/json",
        "application/javascript",
        "text/javascript"
    });
    options.EnableForHttps = true;
});

services.Configure<BrotliCompressionProviderOptions>(options =>
{
    options.Level = CompressionLevel.Optimal;
});

4. Database Connection Pooling


// Optimisation des connexions Entity Framework
services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseSqlServer(connectionString, sqlOptions =>
    {
        sqlOptions.CommandTimeout(30);
        sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 3,
            maxRetryDelay: TimeSpan.FromSeconds(5),
            errorNumbersToAdd: null);
    });
}, ServiceLifetime.Scoped);

// Configuration du pool de connexions
services.AddDbContextPool<ApplicationDbContext>(options =>
{
    options.UseSqlServer(connectionString);
}, poolSize: 128);

5. Streaming et IAsyncEnumerable


[HttpGet("large-dataset")]
public async IAsyncEnumerable<DataItem> GetLargeDatasetStream(
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    var batchSize = 1000;
    var offset = 0;
    
    while (!cancellationToken.IsCancellationRequested)
    {
        var batch = await _repository.GetBatchAsync(offset, batchSize, cancellationToken);
        
        if (!batch.Any())
            break;
            
        foreach (var item in batch)
        {
            yield return item;
        }
        
        offset += batchSize;
    }
}

6. Custom Middleware pour Performance


public class PerformanceMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<PerformanceMiddleware> _logger;
    
    public async Task InvokeAsync(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();
        
        try
        {
            await _next(context);
        }
        finally
        {
            stopwatch.Stop();
            
            var responseTime = stopwatch.ElapsedMilliseconds;
            context.Response.Headers.Add("X-Response-Time", $"{responseTime}ms");
            
            if (responseTime > 1000) // Log slow requests
            {
                _logger.LogWarning(
                    "Slow request: {Method} {Path} took {ResponseTime}ms",
                    context.Request.Method,
                    context.Request.Path,
                    responseTime);
            }
        }
    }
}

7. Optimisation des JSON APIs


// Configuration JSON optimisée
services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.SerializerOptions.WriteIndented = false; // Production
});

// Source generators pour JSON
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
internal partial class UserJsonContext : JsonSerializerContext
{
}

// Usage avec des performances optimales
public async Task<IActionResult> GetUsersOptimized()
{
    var users = await _userService.GetAllAsync();
    return Results.Json(users, UserJsonContext.Default.ListUser);
}

Techniques de Monitoring

8. Application Insights et Métriques Custom


public class MetricsService
{
    private readonly TelemetryClient _telemetryClient;
    
    public void TrackCustomMetric(string name, double value, IDictionary<string, string> properties = null)
    {
        _telemetryClient.TrackMetric(name, value, properties);
    }
    
    public void TrackDependency(string dependencyName, string commandName, 
        DateTimeOffset startTime, TimeSpan duration, bool success)
    {
        _telemetryClient.TrackDependency(dependencyName, commandName, 
            startTime, duration, success);
    }
}

Optimisations Avancées

9. Précompilation des Expressions


public static class PrecompiledExpressions
{
    private static readonly Func<User, bool> IsActiveUser = 
        CompileExpression<User, bool>(u => u.IsActive && u.LastLoginDate > DateTime.Now.AddDays(-30));
    
    private static Func<T, TResult> CompileExpression<T, TResult>(Expression<Func<T, TResult>> expression)
    {
        return expression.Compile();
    }
    
    public static bool CheckIfUserIsActive(User user)
    {
        return IsActiveUser(user);
    }
}

10. Output Caching (ASP.NET Core 7+)


// Configuration
services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => 
        builder.Expire(TimeSpan.FromMinutes(10)));
        
    options.AddPolicy("ApiCache", builder =>
        builder.SetVaryByQuery("page", "pageSize")
               .Expire(TimeSpan.FromMinutes(5)));
});

// Usage dans un controller
[OutputCache(PolicyName = "ApiCache")]
public async Task<IActionResult> GetProducts(int page = 1, int pageSize = 20)
{
    var products = await _productService.GetPagedAsync(page, pageSize);
    return Ok(products);
}

Bonnes Pratiques de Performance

  1. Profilez avant d'optimiser - Utilisez des outils comme dotTrace ou PerfView
  2. Optimisez les goulots d'étranglement - Ne pas optimiser prématurément
  3. Surveillez la mémoire - Évitez les fuites mémoire
  4. Utilisez des patterns asynchrones - async/await partout où c'est pertinent
  5. Optimisez vos requêtes - Indexation et requêtes efficaces

Conclusion

L'optimisation des performances dans ASP.NET Core nécessite une approche holistique combinant techniques de développement, architecture et monitoring. Ces 20 techniques vous donneront une base solide pour créer des applications haute performance.

Partager cet article
42
12

Commentaires (0)

Rejoignez la discussion

Connectez-vous pour partager votre avis et échanger avec la communauté

Première discussion

Soyez le premier à partager votre avis sur cet article !

À propos de l'auteur
Olivier Dupuy

Développeur passionné et créateur de contenu technique. Expert en développement web moderne avec ASP.NET Core, JavaScript, et technologies cloud.

Profil
Articles similaires
API versioning strategies
02 août 2025 0
C# & .NET
Cryptographie post-quantique
02 août 2025 0
C# & .NET
Géolocalisation et cartes interactives
02 août 2025 0
C# & .NET
Navigation rapide
Commentaires (0)