Skip to content

Instantly share code, notes, and snippets.

@waf
Created June 25, 2020 04:53
Show Gist options
  • Save waf/f1c0139a086c79f34bc4ed17d36b95db to your computer and use it in GitHub Desktop.
Save waf/f1c0139a086c79f34bc4ed17d36b95db to your computer and use it in GitHub Desktop.
Regex Memory Benchmarking
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
using BenchmarkDotNet.Running;
using System;
using System.Linq;
using System.Text.RegularExpressions;
// Benchmark Results:
//
// BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.329 (2004/?/20H1)
// Intel Core i5-9400 CPU 2.90GHz (Coffee Lake), 1 CPU, 6 logical and 6 physical cores
// .NET Core SDK=3.1.300
// [Host] : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT
// DefaultJob : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT
//
//
// | Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | Allocated native memory | Native memory leak |
// |-------------- |--------:|---------:|---------:|----------:|----------:|------:|----------:|------------------------:|-------------------:|
// | InstanceRegex | 2.974 s | 0.0106 s | 0.0099 s | 6000.0000 | 3000.0000 | - | 28.7 MB | 9.9 MB | 0.6 MB |
// | StaticRegex | 3.018 s | 0.0132 s | 0.0117 s | 4000.0000 | 1000.0000 | - | 28.8 MB | 9.19 MB | 2.55 MB |
//
// --------------------
// RegexBenchmark.InstanceRegex: DefaultJob
// --------------------
// Native memory allocated per single operation: 10383402 B
// Count of allocated object: 71339
// Native memory leak per single operation: 633642 B
// Count of not deallocated object: 4060
// Count of not deallocated object: 22
//
// --------------------
// RegexBenchmark.StaticRegex: DefaultJob
// --------------------
// Native memory allocated per single operation: 9637421 B
// Count of allocated object: 51677
// Native memory leak per single operation: 2677704 B
// Count of not deallocated object: 18087
// Count of not deallocated object: 33
namespace Benchmarking
{
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run(typeof(Program).Assembly);
}
}
[MemoryDiagnoser]
[NativeMemoryProfiler]
public class RegexBenchmark
{
private const int RegexCount = 1000;
private const RegexOptions MatchOptions = RegexOptions.IgnoreCase | RegexOptions.Compiled;
private readonly string[] regexes;
private readonly string[] input;
public RegexBenchmark()
{
var r = new Random();
// create a bunch of regex strings like "([ajadfjdsgj])|([bdhkckdjlo])|..."
regexes = Enumerable.Range(1, RegexCount).Select(_ => NewRandomRegex(r)).ToArray();
// create a bunch of inputs to match against
input = Enumerable.Range(1, RegexCount).Select(_ => RandomString(r, 10)).ToArray();
string NewRandomRegex(Random r) =>
string.Join("|",
Enumerable
.Range(1, 5)
.Select(_ => "([" + RandomString(r, 10) + "])")
);
}
private static string RandomString(Random r, int length) =>
string.Join("",
Enumerable.Range('a', 26).OrderBy(_ => r.Next()).Take(length).Select(code => (char)code)
);
[Benchmark]
public bool[] InstanceRegex()
{
bool[] matches = new bool[RegexCount];
for (int i = 0; i < RegexCount; i++)
{
var r = new Regex(regexes[i], MatchOptions);
matches[i] = r.IsMatch(input[i]);
}
return matches;
}
[Benchmark]
public bool[] StaticRegex()
{
bool[] matches = new bool[RegexCount];
for (int i = 0; i < RegexCount; i++)
{
matches[i] = Regex.IsMatch(input[i], regexes[i], MatchOptions);
}
return matches;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment