Skip to content

Commit 7b93ee7

Browse files
Update benchmarks
1 parent cee00af commit 7b93ee7

File tree

6 files changed

+266
-178
lines changed

6 files changed

+266
-178
lines changed

tests/ImageSharp.Benchmarks/General/PixelConversion/ITestPixel.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@ public interface ITestPixel<T>
1111
{
1212
void FromRgba32(Rgba32 source);
1313

14+
static abstract T StaticFromRgba32(Rgba32 source);
15+
1416
void FromRgba32(ref Rgba32 source);
1517

1618
void FromBytes(byte r, byte g, byte b, byte a);
1719

1820
void FromVector4(Vector4 source);
1921

22+
static abstract T StaticFromVector4(Vector4 source);
23+
2024
void FromVector4(ref Vector4 source);
2125

2226
Rgba32 ToRgba32();
2327

24-
void CopyToRgba32(ref Rgba32 dest);
28+
void CopyToRgba32(ref Rgba32 destination);
2529

2630
Vector4 ToVector4();
2731

28-
void CopyToVector4(ref Vector4 dest);
32+
void CopyToVector4(ref Vector4 destination);
2933
}

tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs

Lines changed: 115 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
1313

1414
public abstract class PixelConversion_ConvertFromRgba32
1515
{
16-
internal struct ConversionRunner<T>
16+
internal readonly struct ConversionRunner<T>
1717
where T : struct, ITestPixel<T>
1818
{
19-
public readonly T[] Dest;
19+
public readonly T[] Destination;
2020

2121
public readonly Rgba32[] Source;
2222

2323
public ConversionRunner(int count)
2424
{
25-
this.Dest = new T[count];
25+
this.Destination = new T[count];
2626
this.Source = new Rgba32[count];
2727
}
2828

2929
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30-
public void RunByRefConversion()
30+
public readonly void RunByRefConversion()
3131
{
32-
int count = this.Dest.Length;
32+
int count = this.Destination.Length;
3333

34-
ref T destBaseRef = ref this.Dest[0];
34+
ref T destBaseRef = ref this.Destination[0];
3535
ref Rgba32 sourceBaseRef = ref this.Source[0];
3636

3737
for (nuint i = 0; i < (uint)count; i++)
@@ -41,11 +41,11 @@ public void RunByRefConversion()
4141
}
4242

4343
[MethodImpl(MethodImplOptions.AggressiveInlining)]
44-
public void RunByValConversion()
44+
public readonly void RunByValConversion()
4545
{
46-
int count = this.Dest.Length;
46+
int count = this.Destination.Length;
4747

48-
ref T destBaseRef = ref this.Dest[0];
48+
ref T destBaseRef = ref this.Destination[0];
4949
ref Rgba32 sourceBaseRef = ref this.Source[0];
5050

5151
for (nuint i = 0; i < (uint)count; i++)
@@ -55,11 +55,25 @@ public void RunByValConversion()
5555
}
5656

5757
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58-
public void RunFromBytesConversion()
58+
public readonly void RunStaticByValConversion()
5959
{
60-
int count = this.Dest.Length;
60+
int count = this.Destination.Length;
6161

62-
ref T destBaseRef = ref this.Dest[0];
62+
ref T destBaseRef = ref this.Destination[0];
63+
ref Rgba32 sourceBaseRef = ref this.Source[0];
64+
65+
for (nuint i = 0; i < (uint)count; i++)
66+
{
67+
Unsafe.Add(ref destBaseRef, i) = T.StaticFromRgba32(Unsafe.Add(ref sourceBaseRef, i));
68+
}
69+
}
70+
71+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
72+
public readonly void RunFromBytesConversion()
73+
{
74+
int count = this.Destination.Length;
75+
76+
ref T destBaseRef = ref this.Destination[0];
6377
ref Rgba32 sourceBaseRef = ref this.Source[0];
6478

6579
for (nuint i = 0; i < (uint)count; i++)
@@ -74,6 +88,8 @@ public void RunFromBytesConversion()
7488

7589
internal ConversionRunner<TestArgb> PermutedRunnerRgbaToArgb;
7690

91+
internal ConversionRunner<TestRgbaVector> RunnerRgbaToRgbaVector;
92+
7793
[Params(256, 2048)]
7894
public int Count { get; set; }
7995

@@ -82,34 +98,29 @@ public void Setup()
8298
{
8399
this.CompatibleMemLayoutRunner = new ConversionRunner<TestRgba>(this.Count);
84100
this.PermutedRunnerRgbaToArgb = new ConversionRunner<TestArgb>(this.Count);
101+
this.RunnerRgbaToRgbaVector = new ConversionRunner<TestRgbaVector>(this.Count);
85102
}
86103
}
87104

88105
public class PixelConversion_ConvertFromRgba32_Compatible : PixelConversion_ConvertFromRgba32
89106
{
90107
[Benchmark(Baseline = true)]
91-
public void ByRef()
92-
{
93-
this.CompatibleMemLayoutRunner.RunByRefConversion();
94-
}
108+
public void ByRef() => this.CompatibleMemLayoutRunner.RunByRefConversion();
95109

96110
[Benchmark]
97-
public void ByVal()
98-
{
99-
this.CompatibleMemLayoutRunner.RunByValConversion();
100-
}
111+
public void ByVal() => this.CompatibleMemLayoutRunner.RunByValConversion();
101112

102113
[Benchmark]
103-
public void FromBytes()
104-
{
105-
this.CompatibleMemLayoutRunner.RunFromBytesConversion();
106-
}
114+
public void StaticByVal() => this.CompatibleMemLayoutRunner.RunStaticByValConversion();
115+
116+
[Benchmark]
117+
public void FromBytes() => this.CompatibleMemLayoutRunner.RunFromBytesConversion();
107118

108119
[Benchmark]
109120
public void Inline()
110121
{
111122
ref Rgba32 sBase = ref this.CompatibleMemLayoutRunner.Source[0];
112-
ref Rgba32 dBase = ref Unsafe.As<TestRgba, Rgba32>(ref this.CompatibleMemLayoutRunner.Dest[0]);
123+
ref Rgba32 dBase = ref Unsafe.As<TestRgba, Rgba32>(ref this.CompatibleMemLayoutRunner.Destination[0]);
113124

114125
for (nuint i = 0; i < (uint)this.Count; i++)
115126
{
@@ -120,50 +131,46 @@ public void Inline()
120131
/*
121132
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
122133
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
123-
.NET SDK 8.0.100
124-
[Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
125-
DefaultJob : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
126-
127-
128-
| Method | Count | Mean | Error | StdDev | Ratio |
129-
|---------- |------ |-----------:|--------:|--------:|------:|
130-
| ByRef | 256 | 102.5 ns | 0.44 ns | 0.39 ns | 1.00 |
131-
| ByVal | 256 | 102.2 ns | 0.30 ns | 0.25 ns | 1.00 |
132-
| FromBytes | 256 | 200.5 ns | 1.01 ns | 0.90 ns | 1.96 |
133-
| Inline | 256 | 107.0 ns | 0.90 ns | 0.84 ns | 1.04 |
134-
| | | | | | |
135-
| ByRef | 2048 | 770.8 ns | 3.22 ns | 2.86 ns | 1.00 |
136-
| ByVal | 2048 | 770.3 ns | 2.05 ns | 1.92 ns | 1.00 |
137-
| FromBytes | 2048 | 1,546.8 ns | 7.51 ns | 6.66 ns | 2.01 |
138-
| Inline | 2048 | 797.6 ns | 2.90 ns | 2.26 ns | 1.03 |
134+
.NET SDK 8.0.200-preview.23624.5
135+
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
136+
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
137+
138+
139+
| Method | Count | Mean | Error | StdDev | Ratio |
140+
|------------ |------ |-----------:|--------:|--------:|------:|
141+
| ByRef | 256 | 103.4 ns | 0.52 ns | 0.46 ns | 1.00 |
142+
| ByVal | 256 | 103.3 ns | 1.48 ns | 1.38 ns | 1.00 |
143+
| StaticByVal | 256 | 104.0 ns | 0.36 ns | 0.30 ns | 1.01 |
144+
| FromBytes | 256 | 201.8 ns | 1.30 ns | 1.15 ns | 1.95 |
145+
| Inline | 256 | 106.6 ns | 0.40 ns | 0.34 ns | 1.03 |
146+
| | | | | | |
147+
| ByRef | 2048 | 771.5 ns | 3.68 ns | 3.27 ns | 1.00 |
148+
| ByVal | 2048 | 769.7 ns | 3.39 ns | 2.83 ns | 1.00 |
149+
| StaticByVal | 2048 | 773.2 ns | 3.95 ns | 3.50 ns | 1.00 |
150+
| FromBytes | 2048 | 1,555.3 ns | 9.24 ns | 8.19 ns | 2.02 |
151+
| Inline | 2048 | 799.5 ns | 5.91 ns | 4.93 ns | 1.04 |
139152
*/
140153
}
141154

142155
public class PixelConversion_ConvertFromRgba32_Permuted_RgbaToArgb : PixelConversion_ConvertFromRgba32
143156
{
144157
[Benchmark(Baseline = true)]
145-
public void ByRef()
146-
{
147-
this.PermutedRunnerRgbaToArgb.RunByRefConversion();
148-
}
158+
public void ByRef() => this.PermutedRunnerRgbaToArgb.RunByRefConversion();
149159

150160
[Benchmark]
151-
public void ByVal()
152-
{
153-
this.PermutedRunnerRgbaToArgb.RunByValConversion();
154-
}
161+
public void ByVal() => this.PermutedRunnerRgbaToArgb.RunByValConversion();
155162

156163
[Benchmark]
157-
public void FromBytes()
158-
{
159-
this.PermutedRunnerRgbaToArgb.RunFromBytesConversion();
160-
}
164+
public void StaticByVal() => this.PermutedRunnerRgbaToArgb.RunStaticByValConversion();
165+
166+
[Benchmark]
167+
public void FromBytes() => this.PermutedRunnerRgbaToArgb.RunFromBytesConversion();
161168

162169
[Benchmark]
163170
public void InlineShuffle()
164171
{
165172
ref Rgba32 sBase = ref this.PermutedRunnerRgbaToArgb.Source[0];
166-
ref TestArgb dBase = ref this.PermutedRunnerRgbaToArgb.Dest[0];
173+
ref TestArgb dBase = ref this.PermutedRunnerRgbaToArgb.Destination[0];
167174

168175
for (nuint i = 0; i < (uint)this.Count; i++)
169176
{
@@ -181,25 +188,64 @@ public void InlineShuffle()
181188
public void PixelConverter_Rgba32_ToArgb32()
182189
{
183190
Span<byte> source = MemoryMarshal.Cast<Rgba32, byte>(this.PermutedRunnerRgbaToArgb.Source);
184-
Span<byte> dest = MemoryMarshal.Cast<TestArgb, byte>(this.PermutedRunnerRgbaToArgb.Dest);
191+
Span<byte> dest = MemoryMarshal.Cast<TestArgb, byte>(this.PermutedRunnerRgbaToArgb.Destination);
185192

186193
PixelConverter.FromRgba32.ToArgb32(source, dest);
187194
}
188195

189196
/*
190-
RESULTS:
191-
| Method | Count | Mean | Error | StdDev | Median | Ratio | RatioSD |
192-
|------------------------------- |------ |------------:|----------:|----------:|------------:|------:|--------:|
193-
| ByRef | 256 | 288.84 ns | 19.601 ns | 52.319 ns | 268.10 ns | 1.00 | 0.00 |
194-
| ByVal | 256 | 267.97 ns | 1.831 ns | 1.713 ns | 267.85 ns | 0.77 | 0.18 |
195-
| FromBytes | 256 | 266.81 ns | 2.427 ns | 2.270 ns | 266.47 ns | 0.76 | 0.18 |
196-
| InlineShuffle | 256 | 291.41 ns | 5.820 ns | 5.444 ns | 290.17 ns | 0.83 | 0.19 |
197-
| PixelConverter_Rgba32_ToArgb32 | 256 | 38.62 ns | 0.431 ns | 0.403 ns | 38.68 ns | 0.11 | 0.03 |
198-
| | | | | | | | |
199-
| ByRef | 2048 | 2,197.69 ns | 15.826 ns | 14.804 ns | 2,197.25 ns | 1.00 | 0.00 |
200-
| ByVal | 2048 | 2,226.81 ns | 44.266 ns | 62.054 ns | 2,197.17 ns | 1.03 | 0.04 |
201-
| FromBytes | 2048 | 2,181.35 ns | 18.033 ns | 16.868 ns | 2,185.97 ns | 0.99 | 0.01 |
202-
| InlineShuffle | 2048 | 2,233.10 ns | 27.673 ns | 24.531 ns | 2,229.78 ns | 1.02 | 0.01 |
203-
| PixelConverter_Rgba32_ToArgb32 | 2048 | 139.90 ns | 2.152 ns | 3.825 ns | 138.70 ns | 0.06 | 0.00 |
197+
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
198+
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
199+
.NET SDK 8.0.200-preview.23624.5
200+
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
201+
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
202+
203+
204+
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
205+
|------------------------------- |------ |------------:|----------:|---------:|------:|--------:|
206+
| ByRef | 256 | 203.48 ns | 3.318 ns | 3.104 ns | 1.00 | 0.00 |
207+
| ByVal | 256 | 201.46 ns | 2.242 ns | 1.872 ns | 0.99 | 0.02 |
208+
| StaticByVal | 256 | 201.45 ns | 0.791 ns | 0.701 ns | 0.99 | 0.02 |
209+
| FromBytes | 256 | 200.76 ns | 1.365 ns | 1.140 ns | 0.99 | 0.01 |
210+
| InlineShuffle | 256 | 221.65 ns | 2.104 ns | 1.968 ns | 1.09 | 0.02 |
211+
| PixelConverter_Rgba32_ToArgb32 | 256 | 26.23 ns | 0.277 ns | 0.231 ns | 0.13 | 0.00 |
212+
| | | | | | | |
213+
| ByRef | 2048 | 1,561.54 ns | 11.208 ns | 8.751 ns | 1.00 | 0.00 |
214+
| ByVal | 2048 | 1,554.26 ns | 9.607 ns | 8.517 ns | 1.00 | 0.01 |
215+
| StaticByVal | 2048 | 1,562.48 ns | 8.937 ns | 8.360 ns | 1.00 | 0.01 |
216+
| FromBytes | 2048 | 1,552.68 ns | 7.445 ns | 5.812 ns | 0.99 | 0.01 |
217+
| InlineShuffle | 2048 | 1,711.28 ns | 7.559 ns | 6.312 ns | 1.10 | 0.01 |
218+
| PixelConverter_Rgba32_ToArgb32 | 2048 | 94.43 ns | 0.363 ns | 0.322 ns | 0.06 | 0.00 |
219+
*/
220+
}
221+
222+
public class PixelConversion_ConvertFromRgba32_RgbaToRgbaVector : PixelConversion_ConvertFromRgba32
223+
{
224+
[Benchmark(Baseline = true)]
225+
public void ByRef() => this.RunnerRgbaToRgbaVector.RunByRefConversion();
226+
227+
[Benchmark]
228+
public void ByVal() => this.RunnerRgbaToRgbaVector.RunByValConversion();
229+
230+
[Benchmark]
231+
public void StaticByVal() => this.RunnerRgbaToRgbaVector.RunStaticByValConversion();
232+
233+
/*
234+
BenchmarkDotNet v0.13.10, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
235+
11th Gen Intel Core i7-11370H 3.30GHz, 1 CPU, 8 logical and 4 physical cores
236+
.NET SDK 8.0.200-preview.23624.5
237+
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
238+
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
239+
240+
241+
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
242+
|------------ |------ |-----------:|---------:|---------:|------:|--------:|
243+
| ByRef | 256 | 448.5 ns | 4.86 ns | 4.06 ns | 1.00 | 0.00 |
244+
| ByVal | 256 | 447.0 ns | 1.55 ns | 1.21 ns | 1.00 | 0.01 |
245+
| StaticByVal | 256 | 447.4 ns | 1.67 ns | 1.30 ns | 1.00 | 0.01 |
246+
| | | | | | | |
247+
| ByRef | 2048 | 3,577.7 ns | 53.80 ns | 47.69 ns | 1.00 | 0.00 |
248+
| ByVal | 2048 | 3,590.5 ns | 43.59 ns | 36.40 ns | 1.00 | 0.02 |
249+
| StaticByVal | 2048 | 3,604.6 ns | 16.19 ns | 14.36 ns | 1.01 | 0.01 |
204250
*/
205251
}

tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromVector4.cs

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,6 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
1313

1414
public class PixelConversion_ConvertFromVector4
1515
{
16-
[StructLayout(LayoutKind.Sequential)]
17-
private struct TestRgbaVector : ITestPixel<TestRgbaVector>
18-
{
19-
private Vector4 v;
20-
21-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
22-
public void FromVector4(Vector4 p)
23-
{
24-
this.v = p;
25-
}
26-
27-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28-
public void FromVector4(ref Vector4 p)
29-
{
30-
this.v = p;
31-
}
32-
33-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
34-
public Vector4 ToVector4() => this.v;
35-
36-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37-
public void CopyToVector4(ref Vector4 dest)
38-
{
39-
dest = this.v;
40-
}
41-
42-
public void FromRgba32(Rgba32 source) => throw new System.NotImplementedException();
43-
44-
public void FromRgba32(ref Rgba32 source) => throw new System.NotImplementedException();
45-
46-
public void FromBytes(byte r, byte g, byte b, byte a) => throw new System.NotImplementedException();
47-
48-
public Rgba32 ToRgba32() => throw new System.NotImplementedException();
49-
50-
public void CopyToRgba32(ref Rgba32 dest) => throw new System.NotImplementedException();
51-
}
52-
5316
private struct ConversionRunner<T>
5417
where T : struct, ITestPixel<T>
5518
{

0 commit comments

Comments
 (0)