// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; 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; } } }