File: TransformersBenchmark.cs
Web Access
Project: src\src\OpenApi\perf\Microbenchmarks\Microsoft.AspNetCore.OpenApi.Microbenchmarks.csproj (Microsoft.AspNetCore.OpenApi.Microbenchmarks)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
 
namespace Microsoft.AspNetCore.OpenApi.Microbenchmarks;
 
/// <summary>
/// The following benchmarks are used to assess the memory and performance
/// impact of different types of transformers. In particular, we want to
/// measure the impact of (a) context-object creation and caching and (b)
/// enumerator usage when processing operations in a given document.
/// </summary>
public class TransformersBenchmark : OpenApiDocumentServiceTestBase
{
    [Params(10, 100, 1000)]
    public int TransformerCount { get; set; }
 
    private readonly IEndpointRouteBuilder _builder = CreateBuilder();
    private readonly OpenApiOptions _options = new OpenApiOptions();
    private OpenApiDocumentService _documentService;
 
    [GlobalSetup(Target = nameof(OperationTransformerAsDelegate))]
    public void OperationTransformerAsDelegate_Setup()
    {
        _builder.MapGet("/", () => { });
        for (var i = 0; i <= TransformerCount; i++)
        {
            _options.UseOperationTransformer((operation, context, token) =>
            {
                operation.Description = "New Description";
                return Task.CompletedTask;
            });
        }
        _documentService = CreateDocumentService(_builder, _options);
    }
 
    [GlobalSetup(Target = nameof(ActivatedDocumentTransformer))]
    public void ActivatedDocumentTransformer_Setup()
    {
        _builder.MapGet("/", () => { });
        for (var i = 0; i <= TransformerCount; i++)
        {
            _options.UseTransformer<ActivatedTransformer>();
        }
        _documentService = CreateDocumentService(_builder, _options);
    }
 
    [GlobalSetup(Target = nameof(DocumentTransformerAsDelegate))]
    public void DocumentTransformerAsDelegate_Delegate()
    {
        _builder.MapGet("/", () => { });
        for (var i = 0; i <= TransformerCount; i++)
        {
            _options.UseTransformer((document, context, token) =>
            {
                document.Info.Description = "New Description";
                return Task.CompletedTask;
            });
        }
        _documentService = CreateDocumentService(_builder, _options);
    }
 
    [GlobalSetup(Target = nameof(SchemaTransformer))]
    public void SchemaTransformer_Setup()
    {
        _builder.MapPost("/", (Todo todo) => todo);
        for (var i = 0; i <= TransformerCount; i++)
        {
            _options.UseSchemaTransformer((schema, context, token) =>
            {
                if (context.Type == typeof(Todo) && context.ParameterDescription != null)
                {
                    schema.Extensions["x-my-extension"] = new OpenApiString(context.ParameterDescription.Name);
                }
                else
                {
                    schema.Extensions["x-my-extension"] = new OpenApiString("response");
                }
                return Task.CompletedTask;
            });
        }
        _documentService = CreateDocumentService(_builder, _options);
    }
 
    [Benchmark]
    public async Task OperationTransformerAsDelegate()
    {
        await _documentService.GetOpenApiDocumentAsync();
    }
 
    [Benchmark]
    public async Task ActivatedDocumentTransformer()
    {
        await _documentService.GetOpenApiDocumentAsync();
    }
 
    [Benchmark]
    public async Task DocumentTransformerAsDelegate()
    {
        await _documentService.GetOpenApiDocumentAsync();
    }
 
    [Benchmark]
    public async Task SchemaTransformer()
    {
        await _documentService.GetOpenApiDocumentAsync();
    }
 
    private class ActivatedTransformer : IOpenApiDocumentTransformer
    {
        public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
        {
            document.Info.Description = "Info Description";
            return Task.CompletedTask;
        }
    }
}