File: Matching\JumpTableSingleEntryBenchmark.cs
Web Access
Project: src\src\Http\Routing\perf\Microbenchmarks\Microsoft.AspNetCore.Routing.Microbenchmarks.csproj (Microsoft.AspNetCore.Routing.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;
 
namespace Microsoft.AspNetCore.Routing.Matching;
 
public class JumpTableSingleEntryBenchmark
{
    private JumpTable _default;
    private JumpTable _trie;
    private JumpTable _vectorTrie;
    private JumpTable _ascii;
 
    private string[] _strings;
    private PathSegment[] _segments;
 
    [GlobalSetup]
    public void Setup()
    {
        _default = new SingleEntryJumpTable(0, -1, "hello-world", 1);
        _trie = new ILEmitTrieJumpTable(0, -1, new[] { ("hello-world", 1), }, vectorize: false, _default);
        _vectorTrie = new ILEmitTrieJumpTable(0, -1, new[] { ("hello-world", 1), }, vectorize: true, _default);
        _ascii = new SingleEntryAsciiJumpTable(0, -1, "hello-world", 1);
 
        _strings = new string[]
        {
                "index/foo/2",
                "index/hello-world1/2",
                "index/hello-world/2",
                "index//2",
                "index/hillo-goodbye/2",
        };
        _segments = new PathSegment[]
        {
                new PathSegment(6, 3),
                new PathSegment(6, 12),
                new PathSegment(6, 11),
                new PathSegment(6, 0),
                new PathSegment(6, 13),
        };
    }
 
    [Benchmark(Baseline = true, OperationsPerInvoke = 5)]
    public int Baseline()
    {
        var strings = _strings;
        var segments = _segments;
 
        int destination = 0;
        for (var i = 0; i < strings.Length; i++)
        {
            var @string = strings[i];
            var segment = segments[i];
 
            if (segment.Length == 0)
            {
                destination = -1;
            }
            else if (segment.Length != "hello-world".Length)
            {
                destination = 1;
            }
            else
            {
                destination = string.Compare(
                    @string,
                    segment.Start,
                    "hello-world",
                    0,
                    segment.Length,
                    StringComparison.OrdinalIgnoreCase);
            }
        }
 
        return destination;
    }
 
    [Benchmark(OperationsPerInvoke = 5)]
    public int Default()
    {
        var strings = _strings;
        var segments = _segments;
 
        var destination = 0;
        for (var i = 0; i < strings.Length; i++)
        {
            destination = _default.GetDestination(strings[i], segments[i]);
        }
 
        return destination;
    }
 
    [Benchmark(OperationsPerInvoke = 5)]
    public int Ascii()
    {
        var strings = _strings;
        var segments = _segments;
 
        var destination = 0;
        for (var i = 0; i < strings.Length; i++)
        {
            destination = _ascii.GetDestination(strings[i], segments[i]);
        }
 
        return destination;
    }
 
    [Benchmark(OperationsPerInvoke = 5)]
    public int Trie()
    {
        var strings = _strings;
        var segments = _segments;
 
        var destination = 0;
        for (var i = 0; i < strings.Length; i++)
        {
            destination = _trie.GetDestination(strings[i], segments[i]);
        }
 
        return destination;
    }
 
    [Benchmark(OperationsPerInvoke = 5)]
    public int VectorTrie()
    {
        var strings = _strings;
        var segments = _segments;
 
        var destination = 0;
        for (var i = 0; i < strings.Length; i++)
        {
            destination = _vectorTrie.GetDestination(strings[i], segments[i]);
        }
 
        return destination;
    }
}