Path.GetFileName performance improvements in .NET 8 versus .NET 7
Date Added (UTC):
07 Apr 2024 @ 21:23
Date Updated (UTC):07 Apr 2024 @ 21:35
.NET Version(s): Tag(s):
Added By:
.NET Developer and tech lead from Ireland!
Benchmark Results:
Benchmark Code:
using BenchmarkDotNet.Attributes;
using System.IO;
using System;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;
[Config(typeof(Config))]
[HideColumns(Column.Job, Column.RatioSD, Column.AllocRatio)]
[MemoryDiagnoser]
public class GetFileNameBenchmark
{
private string _path = Path.Join(Path.GetTempPath(), "SomeFileName.cs");
[Benchmark]
public ReadOnlySpan<char> GetFileName() => Path.GetFileName(_path.AsSpan());
private class Config : ManualConfig
{
public Config()
{
AddJob(Job.Default.WithId(".NET 7").WithRuntime(CoreRuntime.Core70).AsBaseline());
AddJob(Job.Default.WithId(".NET 8").WithRuntime(CoreRuntime.Core80));
SummaryStyle =
SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
}
}
}
Powered by SharpLab
// .NET 7, .NET 8
public ReadOnlySpan<char> GetFileName()
{
return Path.GetFileName(MemoryExtensions.AsSpan(_path));
}
Powered by SharpLab
// .NET 7
.method public hidebysig
instance valuetype [System.Runtime]System.ReadOnlySpan`1<char> GetFileName () cil managed
{
.custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor(int32, string) = (
01 00 1d 00 00 00 01 5f 00 00
)
// Method begins at RVA 0x207f
// Code size 17 (0x11)
.maxstack 8
// sequence point: (line 30, col 48) to (line 30, col 80) in _
IL_0000: ldarg.0
IL_0001: ldfld string GetFileNameBenchmark::_path
IL_0006: call valuetype [System.Runtime]System.ReadOnlySpan`1<char> [System.Memory]System.MemoryExtensions::AsSpan(string)
IL_000b: call valuetype [System.Runtime]System.ReadOnlySpan`1<char> [System.Runtime]System.IO.Path::GetFileName(valuetype [System.Runtime]System.ReadOnlySpan`1<char>)
IL_0010: ret
}
// .NET 8
.method public hidebysig
instance valuetype [System.Runtime]System.ReadOnlySpan`1<char> GetFileName () cil managed
{
.custom instance void [BenchmarkDotNet.Annotations]BenchmarkDotNet.Attributes.BenchmarkAttribute::.ctor(int32, string) = (
01 00 1d 00 00 00 01 5f 00 00
)
// Method begins at RVA 0x2050
// Code size 17 (0x11)
.maxstack 8
// sequence point: (line 30, col 48) to (line 30, col 80) in _
IL_0000: ldarg.0
IL_0001: ldfld string GetFileNameBenchmark::_path
IL_0006: call valuetype [System.Runtime]System.ReadOnlySpan`1<char> [System.Memory]System.MemoryExtensions::AsSpan(string)
IL_000b: call valuetype [System.Runtime]System.ReadOnlySpan`1<char> [System.Runtime]System.IO.Path::GetFileName(valuetype [System.Runtime]System.ReadOnlySpan`1<char>)
IL_0010: ret
}
Powered by SharpLab
|
|
Benchmark Description:
[PR](https://github.com/dotnet/runtime/pull/75318)
The provided benchmark code is designed to measure the performance of retrieving the file name from a file path using the `Path.GetFileName` method in .NET, specifically comparing its performance across different .NET versions. The benchmark is set up using BenchmarkDotNet, a powerful .NET library for benchmarking code performance. Let's break down the setup and the rationale behind the benchmark method.
### General Setup
- **BenchmarkDotNet Attributes**: The code uses several BenchmarkDotNet attributes to configure the benchmark. `[Config(typeof(Config))]` specifies the configuration class to use. `[HideColumns]` hides specific columns in the output report for clarity. `[MemoryDiagnoser]` enables memory diagnostics to measure memory allocations.
- **.NET Versions**: The benchmark is configured to run against two different .NET versions, .NET 7 and .NET 8, allowing for a direct comparison of performance across these versions. This is achieved through the `Config` class, which specifies two jobs with different runtimes (`CoreRuntime.Core70` and `CoreRuntime.Core80`).
- **Configuration Class (`Config`)**: This class extends `ManualConfig` from BenchmarkDotNet and is used to customize the benchmark's configuration. It adds two jobs for .NET 7 and .NET 8, sets one as the baseline for comparison, and customizes the summary style to display ratios in percentage.
### Benchmark Method: `GetFileName`
- **Purpose**: The `GetFileName` method benchmarks the performance of extracting the file name from a file path using the `Path.GetFileName` method. This operation is common in file handling and processing scenarios, making its performance critical for applications that deal with file systems extensively.
- **Performance Aspect**: This benchmark specifically measures the time it takes to execute `Path.GetFileName` on a `ReadOnlySpan<char>` representing a file path. The use of `ReadOnlySpan<char>` is noteworthy as it represents a more modern approach to handling text in .NET, designed for performance by avoiding unnecessary allocations.
- **Why It's Important**: Understanding the performance of file path manipulation methods is crucial for optimizing file I/O operations. Faster execution times can lead to significant performance improvements in applications that frequently access the file system. Additionally, comparing performance across .NET versions helps developers make informed decisions about upgrading their applications to take advantage of performance improvements in newer versions.
- **Expected Results/Insights**: By running this benchmark, you should expect to see how the performance of `Path.GetFileName` varies between .NET 7 and .NET 8. Ideally, newer .NET versions would offer improved performance due to optimizations in the runtime and libraries. The memory diagnostics enabled by `[MemoryDiagnoser]` will also provide insights into any memory allocations that occur during the execution of the method, which is important for understanding the overall efficiency of the operation.
In summary, this benchmark is designed to provide a focused comparison of the performance of a common file path manipulation operation across different .NET versions, offering valuable insights for developers looking to optimize file handling in their applications.