Skip to content

Commit f8b9b17

Browse files
committed
Add BenchmarkDotNet project for parse, serialize, equals, and hash benchmarks
1 parent d709093 commit f8b9b17

File tree

6 files changed

+291
-0
lines changed

6 files changed

+291
-0
lines changed

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
</PropertyGroup>
55

66
<ItemGroup>
7+
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
78
<PackageVersion Include="MinVer" Version="7.0.0" />
89
<PackageVersion Include="xunit.v3" Version="3.2.2" />
910
</ItemGroup>

PackageUrl.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
</Folder>
77
<Project Path="src/PackageUrl.csproj" />
88
<Project Path="tests/PackageUrl.Tests.csproj" />
9+
<Project Path="benchmarks/PackageUrl.Benchmarks.csproj" />
910
</Solution>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net10.0</TargetFramework>
4+
<OutputType>Exe</OutputType>
5+
<IsPackable>false</IsPackable>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<PackageReference Include="BenchmarkDotNet" />
9+
</ItemGroup>
10+
<ItemGroup>
11+
<ProjectReference Include="..\src\PackageUrl.csproj" />
12+
</ItemGroup>
13+
</Project>

benchmarks/PackageUrlBenchmarks.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System.Collections.Generic;
2+
using BenchmarkDotNet.Attributes;
3+
using BenchmarkDotNet.Configs;
4+
5+
namespace PackageUrl.Benchmarks;
6+
7+
[MemoryDiagnoser]
8+
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
9+
public class PackageUrlBenchmarks
10+
{
11+
private readonly Dictionary<string, string> _purls = new()
12+
{
13+
["Minimal"] = "pkg:npm/[email protected]",
14+
["Namespace"] = "pkg:maven/org.apache.commons/[email protected]",
15+
["Qualifiers"] =
16+
"pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io",
17+
["Full"] =
18+
"pkg:maven/org.apache/[email protected]?classifier=sources&repository_url=repo.spring.io#src/main/java",
19+
};
20+
21+
private readonly Dictionary<string, PackageUrl> _parsed = new();
22+
23+
[ParamsSource(nameof(PurlNames))]
24+
public string Purl { get; set; } = null!;
25+
26+
public static IEnumerable<string> PurlNames => ["Minimal", "Namespace", "Qualifiers", "Full"];
27+
28+
[GlobalSetup]
29+
public void Setup()
30+
{
31+
foreach (var kvp in _purls)
32+
{
33+
_parsed[kvp.Key] = new PackageUrl(kvp.Value);
34+
}
35+
}
36+
37+
// --- Parse ---
38+
39+
[Benchmark(Baseline = true)]
40+
[BenchmarkCategory("Parse")]
41+
public PackageUrl Parse() => new(_purls[Purl]);
42+
43+
// --- ToString ---
44+
45+
[Benchmark(Baseline = true)]
46+
[BenchmarkCategory("ToString")]
47+
public string Serialize() => _parsed[Purl].ToString();
48+
49+
// --- Equals ---
50+
51+
[Benchmark(Baseline = true)]
52+
[BenchmarkCategory("Equals")]
53+
public bool Equal()
54+
{
55+
var purl = _parsed[Purl];
56+
return purl.Equals(purl);
57+
}
58+
59+
// --- GetHashCode ---
60+
61+
[Benchmark(Baseline = true)]
62+
[BenchmarkCategory("GetHashCode")]
63+
public int Hash() => _parsed[Purl].GetHashCode();
64+
}

benchmarks/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using BenchmarkDotNet.Running;
2+
3+
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

benchmarks/packages.lock.json

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
{
2+
"version": 2,
3+
"dependencies": {
4+
"net10.0": {
5+
"BenchmarkDotNet": {
6+
"type": "Direct",
7+
"requested": "[0.15.8, )",
8+
"resolved": "0.15.8",
9+
"contentHash": "paCfrWxSeHqn3rUZc0spYXVFnHCF0nzRhG0nOLnyTjZYs8spsimBaaNmb3vwqvALKIplbYq/TF393vYiYSnh/Q==",
10+
"dependencies": {
11+
"BenchmarkDotNet.Annotations": "0.15.8",
12+
"CommandLineParser": "2.9.1",
13+
"Gee.External.Capstone": "2.3.0",
14+
"Iced": "1.21.0",
15+
"Microsoft.CodeAnalysis.CSharp": "4.14.0",
16+
"Microsoft.Diagnostics.Runtime": "3.1.512801",
17+
"Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.21",
18+
"Microsoft.DotNet.PlatformAbstractions": "3.1.6",
19+
"Perfolizer": "[0.6.1]",
20+
"System.Management": "9.0.5"
21+
}
22+
},
23+
"GitVersion.MsBuild": {
24+
"type": "Direct",
25+
"requested": "[5.8.1, )",
26+
"resolved": "5.8.1",
27+
"contentHash": "WR+50tZK/ZO51RhcNObEZyIN+b7jt6YQOnUdrnkDhi+kPWm00TLXIUci2hGIgE617iaWdkbmkleBbIFwPhH0oQ=="
28+
},
29+
"Microsoft.SourceLink.GitHub": {
30+
"type": "Direct",
31+
"requested": "[10.0.201, )",
32+
"resolved": "10.0.201",
33+
"contentHash": "qxYAmO4ktzd9L+HMdnqWucxpu7bI9undPyACXOMqPyhaiMtbpbYL/n0ACyWIJlbyEJrXFwxiOaBOSasLtDvsCg==",
34+
"dependencies": {
35+
"Microsoft.Build.Tasks.Git": "10.0.201",
36+
"Microsoft.SourceLink.Common": "10.0.201",
37+
"System.IO.Hashing": "10.0.5"
38+
}
39+
},
40+
"BenchmarkDotNet.Annotations": {
41+
"type": "Transitive",
42+
"resolved": "0.15.8",
43+
"contentHash": "hfucY0ycAsB0SsoaZcaAp9oq5wlWBJcylvEJb9pmvdYUx6PD6S4mDiYnZWjdjAlLhIpe/xtGCwzORfzAzPqvzA=="
44+
},
45+
"CommandLineParser": {
46+
"type": "Transitive",
47+
"resolved": "2.9.1",
48+
"contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
49+
},
50+
"Gee.External.Capstone": {
51+
"type": "Transitive",
52+
"resolved": "2.3.0",
53+
"contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
54+
},
55+
"Iced": {
56+
"type": "Transitive",
57+
"resolved": "1.21.0",
58+
"contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
59+
},
60+
"Microsoft.Build.Tasks.Git": {
61+
"type": "Transitive",
62+
"resolved": "10.0.201",
63+
"contentHash": "DMYBnrFZvLnBKn14VavEuuIr31CY6YY2i2L9P8DorS/Qp6ifRR8ZPLdJCFLFfjikNq8DykbYyLd/RP6lSqHcWw==",
64+
"dependencies": {
65+
"System.IO.Hashing": "10.0.5"
66+
}
67+
},
68+
"Microsoft.CodeAnalysis.Analyzers": {
69+
"type": "Transitive",
70+
"resolved": "3.11.0",
71+
"contentHash": "v/EW3UE8/lbEYHoC2Qq7AR/DnmvpgdtAMndfQNmpuIMx/Mto8L5JnuCfdBYtgvalQOtfNCnxFejxuRrryvUTsg=="
72+
},
73+
"Microsoft.CodeAnalysis.Common": {
74+
"type": "Transitive",
75+
"resolved": "4.14.0",
76+
"contentHash": "PC3tuwZYnC+idaPuoC/AZpEdwrtX7qFpmnrfQkgobGIWiYmGi5MCRtl5mx6QrfMGQpK78X2lfIEoZDLg/qnuHg==",
77+
"dependencies": {
78+
"Microsoft.CodeAnalysis.Analyzers": "3.11.0"
79+
}
80+
},
81+
"Microsoft.CodeAnalysis.CSharp": {
82+
"type": "Transitive",
83+
"resolved": "4.14.0",
84+
"contentHash": "568a6wcTivauIhbeWcCwfWwIn7UV7MeHEBvFB2uzGIpM2OhJ4eM/FZ8KS0yhPoNxnSpjGzz7x7CIjTxhslojQA==",
85+
"dependencies": {
86+
"Microsoft.CodeAnalysis.Analyzers": "3.11.0",
87+
"Microsoft.CodeAnalysis.Common": "[4.14.0]"
88+
}
89+
},
90+
"Microsoft.Diagnostics.NETCore.Client": {
91+
"type": "Transitive",
92+
"resolved": "0.2.510501",
93+
"contentHash": "juoqJYMDs+lRrrZyOkXXMImJHneCF23cuvO4waFRd2Ds7j+ZuGIPbJm0Y/zz34BdeaGiiwGWraMUlln05W1PCQ==",
94+
"dependencies": {
95+
"Microsoft.Extensions.Logging": "6.0.0"
96+
}
97+
},
98+
"Microsoft.Diagnostics.Runtime": {
99+
"type": "Transitive",
100+
"resolved": "3.1.512801",
101+
"contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==",
102+
"dependencies": {
103+
"Microsoft.Diagnostics.NETCore.Client": "0.2.410101"
104+
}
105+
},
106+
"Microsoft.Diagnostics.Tracing.TraceEvent": {
107+
"type": "Transitive",
108+
"resolved": "3.1.21",
109+
"contentHash": "/OrJFKaojSR6TkUKtwh8/qA9XWNtxLrXMqvEb89dBSKCWjaGVTbKMYodIUgF5deCEtmd6GXuRerciXGl5bhZ7Q==",
110+
"dependencies": {
111+
"Microsoft.Diagnostics.NETCore.Client": "0.2.510501",
112+
"System.Reflection.TypeExtensions": "4.7.0"
113+
}
114+
},
115+
"Microsoft.DotNet.PlatformAbstractions": {
116+
"type": "Transitive",
117+
"resolved": "3.1.6",
118+
"contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
119+
},
120+
"Microsoft.Extensions.DependencyInjection": {
121+
"type": "Transitive",
122+
"resolved": "6.0.0",
123+
"contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
124+
"dependencies": {
125+
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
126+
}
127+
},
128+
"Microsoft.Extensions.DependencyInjection.Abstractions": {
129+
"type": "Transitive",
130+
"resolved": "6.0.0",
131+
"contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg=="
132+
},
133+
"Microsoft.Extensions.Logging": {
134+
"type": "Transitive",
135+
"resolved": "6.0.0",
136+
"contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
137+
"dependencies": {
138+
"Microsoft.Extensions.DependencyInjection": "6.0.0",
139+
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
140+
"Microsoft.Extensions.Logging.Abstractions": "6.0.0",
141+
"Microsoft.Extensions.Options": "6.0.0"
142+
}
143+
},
144+
"Microsoft.Extensions.Logging.Abstractions": {
145+
"type": "Transitive",
146+
"resolved": "6.0.0",
147+
"contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA=="
148+
},
149+
"Microsoft.Extensions.Options": {
150+
"type": "Transitive",
151+
"resolved": "6.0.0",
152+
"contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
153+
"dependencies": {
154+
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
155+
"Microsoft.Extensions.Primitives": "6.0.0"
156+
}
157+
},
158+
"Microsoft.Extensions.Primitives": {
159+
"type": "Transitive",
160+
"resolved": "6.0.0",
161+
"contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ=="
162+
},
163+
"Microsoft.SourceLink.Common": {
164+
"type": "Transitive",
165+
"resolved": "10.0.201",
166+
"contentHash": "QbBYhkjgL6rCnBfDbzsAJLlsad13TlBHqYCFDIw56OO2g6ix+9RsmY8uxiQGdWwFKbZXaXyAA6jDCzFYVGCZDw=="
167+
},
168+
"Perfolizer": {
169+
"type": "Transitive",
170+
"resolved": "0.6.1",
171+
"contentHash": "CR1QmWg4XYBd1Pb7WseP+sDmV8nGPwvmowKynExTqr3OuckIGVMhvmN4LC5PGzfXqDlR295+hz/T7syA1CxEqA==",
172+
"dependencies": {
173+
"Pragmastat": "3.2.4"
174+
}
175+
},
176+
"Pragmastat": {
177+
"type": "Transitive",
178+
"resolved": "3.2.4",
179+
"contentHash": "I5qFifWw/gaTQT52MhzjZpkm/JPlfjSeO/DTZJjO7+hTKI+0aGRgOgZ3NN6D96dDuuqbIAZSeA5RimtHjqrA2A=="
180+
},
181+
"System.CodeDom": {
182+
"type": "Transitive",
183+
"resolved": "9.0.5",
184+
"contentHash": "cuzLM2MWutf9ZBEMPYYfd0DXwYdvntp7VCT6a/wvbKCa2ZuvGmW74xi+YBa2mrfEieAXqM4TNKlMmSnfAfpUoQ=="
185+
},
186+
"System.IO.Hashing": {
187+
"type": "Transitive",
188+
"resolved": "10.0.5",
189+
"contentHash": "8IBJWcCT9+e4Bmevm4T7+fQEiAh133KGiz4oiVTgJckd3Q76OFdR1falgn9lpz7+C4HJvogCDJeAa2QmvbeVtg=="
190+
},
191+
"System.Management": {
192+
"type": "Transitive",
193+
"resolved": "9.0.5",
194+
"contentHash": "n6o9PZm9p25+zAzC3/48K0oHnaPKTInRrxqFq1fi/5TPbMLjuoCm/h//mS3cUmSy+9AO1Z+qsC/Ilt/ZFatv5Q==",
195+
"dependencies": {
196+
"System.CodeDom": "9.0.5"
197+
}
198+
},
199+
"System.Reflection.TypeExtensions": {
200+
"type": "Transitive",
201+
"resolved": "4.7.0",
202+
"contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA=="
203+
},
204+
"packageurl-dotnet": {
205+
"type": "Project"
206+
}
207+
}
208+
}
209+
}

0 commit comments

Comments
 (0)