.NET 9 String.Contains("X") performance improvement
Date Added (UTC):
08 Apr 2024 @ 02:44
Date Updated (UTC):23 Apr 2024 @ 16:21
.NET Version(s): Tag(s):
#.Net9PerfImprovement #StringComparison #Strings
Added By:
.NET Developer and tech lead from Ireland!
Benchmark Results:
Benchmark Code:
Originally imported from :
https://gist.github.com/davepcallan/197b22fe4c5f76ecec717f845d033939on 23 Apr 2024 @ 16:21 (UTC) .
The original benchmark may have changed.
https://gist.github.com/davepcallan/197b22fe4c5f76ecec717f845d033939
The original benchmark may have changed.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
[Config(typeof(Config))]
[HideColumns(Column.Job, Column.RatioSD, Column.AllocRatio)]
[MemoryDiagnoser]
public class StringContains
{
readonly string _inputString =
"Permission is hereby granted, free of charge, to any person obtaining " +
"a copy of the Unicode data files and any associated documentation";
[Benchmark]
public bool Contains_string() => _inputString.Contains("X");
private class Config : ManualConfig
{
public Config()
{
AddJob(Job.Default.WithId(".NET 8").WithRuntime(CoreRuntime.Core80).AsBaseline());
AddJob(Job.Default.WithId(".NET 9").WithRuntime(CoreRuntime.Core90));
SummaryStyle =
SummaryStyle.Default.WithRatioStyle(RatioStyle.Trend);
}
}
}
Powered by SharpLab
// .NET 8
public bool Contains_string()
{
return _inputString.Contains("X");
}
Powered by SharpLab
// .NET 8
.method public hidebysig
instance bool Contains_string () cil managed
{
.custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor(int32, string) = (
01 00 1f 00 00 00 01 5f 00 00
)
// Method begins at RVA 0x2076
// Code size 17 (0x11)
.maxstack 8
// sequence point: (line 32, col 38) to (line 32, col 64) in _
IL_0000: ldarg.0
IL_0001: ldfld string StringContains::_inputString
IL_0006: ldstr "X"
IL_000b: callvirt instance bool [System.Runtime]System.String::Contains(string)
IL_0010: ret
}
Powered by SharpLab
|
Benchmark Description:
This performance optimization redirects calls into string.Contains("x") to string.Contains('x') for single char literals.
Even though devs should ideally be using the right API I really like when the runtime (and/or compiler) can do these optimizations for us.
[PR](https://github.com/dotnet/runtime/pull/97632)
### General Setup Overview
The benchmark setup provided is designed to evaluate the performance of a specific operation in .NET applications, specifically the `String.Contains` method. This is done using the BenchmarkDotNet library, a powerful tool for benchmarking .NET code. The configuration and execution of the benchmarks are defined using attributes and a custom configuration class.
- **.NET Versions:** The benchmarks are configured to run against two different versions of the .NET runtime: .NET 8 and .NET 9. This allows for comparison across different runtime versions to observe performance improvements or regressions.
- **Configuration (Config class):** A custom configuration class named `Config` is defined, which extends `ManualConfig`. Within this class, two jobs are added, one for each .NET runtime version (.NET 8 as the baseline and .NET 9). The `SummaryStyle` is set to display trends in the ratio of performance between different runs, which helps in easily spotting performance changes.
- **BenchmarkDotNet Attributes:**
- `@Config(typeof(Config))` specifies the configuration to use for the benchmark class.
- `@HideColumns` hides specific columns in the output report, focusing on the most relevant data.
- `@MemoryDiagnoser` enables memory diagnostics, allowing the benchmark to report on memory allocations.
### Benchmark Method: `Contains_string`
#### Purpose
The `Contains_string` method is designed to benchmark the performance of the `String.Contains` method in .NET. This method checks if the input string contains a specific substring ("X" in this case).
#### Performance Aspect
- **String Search Performance:** It measures how efficiently the .NET runtime can search for a substring within a larger string. This is a common operation in many applications, making it a valuable aspect to benchmark.
- **Memory Usage:** With the `MemoryDiagnoser` attribute, the benchmark also provides insights into the memory allocations involved in performing the `Contains` operation. This can help in understanding the memory efficiency of string operations in .NET.
#### Expected Results and Insights
- **Runtime Comparison:** By running this benchmark against different .NET versions, you can observe how the performance of the `String.Contains` method has evolved. Improvements in runtime or library implementations can lead to faster execution times in newer versions.
- **Memory Allocation Insights:** The memory diagnostics will show if there are significant differences in memory allocations when performing string search operations across different .NET versions. Ideally, efficient memory usage is desirable alongside fast execution times.
- **Performance Trends:** The configuration is set to highlight performance trends, so you should expect to see whether the operation becomes faster, slower, or remains consistent across the versions tested. This can inform decisions on upgrading projects to newer .NET versions based on performance considerations.
In summary, this benchmark setup is tailored to provide detailed insights into the performance of string search operations across different .NET runtime versions, focusing on execution speed and memory efficiency. The insights gained can guide optimization efforts and inform decisions regarding .NET version upgrades in projects where string manipulation performance is critical.