Skip to content

Commit 8e21937

Browse files
Merge pull request #1534 from SixLabors/af/JpegEncoder-profiling
Better JpegEncoder profiling & benchmarks
2 parents 27135a0 + 4bd6c04 commit 8e21937

File tree

6 files changed

+37
-12
lines changed

6 files changed

+37
-12
lines changed

src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ internal partial struct Block8x8F : IEquatable<Block8x8F>
5959
/// <returns>The float value at the specified index</returns>
6060
public float this[int idx]
6161
{
62-
[MethodImpl(InliningOptions.ShortMethod)]
62+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6363
get
6464
{
6565
GuardBlockIndex(idx);
6666
ref float selfRef = ref Unsafe.As<Block8x8F, float>(ref this);
6767
return Unsafe.Add(ref selfRef, idx);
6868
}
6969

70-
[MethodImpl(InliningOptions.ShortMethod)]
70+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7171
set
7272
{
7373
GuardBlockIndex(idx);

src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private set
7575
}
7676
}
7777

78-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
78+
[MethodImpl(InliningOptions.ShortMethod)]
7979
public void Update(Buffer2D<T> buffer, int startY)
8080
{
8181
// We don't actually have to assign values outside of the

src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant)
315315
/// <param name="bits">The packed bits.</param>
316316
/// <param name="count">The number of bits</param>
317317
/// <param name="emitBufferBase">The reference to the emitBuffer.</param>
318-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
318+
[MethodImpl(InliningOptions.ShortMethod)]
319319
private void Emit(uint bits, uint count, ref byte emitBufferBase)
320320
{
321321
count += this.bitCount;
@@ -356,7 +356,7 @@ private void Emit(uint bits, uint count, ref byte emitBufferBase)
356356
/// <param name="index">The index of the Huffman encoder</param>
357357
/// <param name="value">The value to encode.</param>
358358
/// <param name="emitBufferBase">The reference to the emit buffer.</param>
359-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
359+
[MethodImpl(InliningOptions.ShortMethod)]
360360
private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase)
361361
{
362362
uint x = HuffmanLut.TheHuffmanLut[(int)index].Values[value];
@@ -370,7 +370,7 @@ private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase)
370370
/// <param name="runLength">The number of copies to encode.</param>
371371
/// <param name="value">The value to encode.</param>
372372
/// <param name="emitBufferBase">The reference to the emit buffer.</param>
373-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
373+
[MethodImpl(InliningOptions.ShortMethod)]
374374
private void EmitHuffRLE(HuffIndex index, int runLength, int value, ref byte emitBufferBase)
375375
{
376376
int a = value;

tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@ public class EncodeJpeg
1616
private Stream bmpStream;
1717
private SDImage bmpDrawing;
1818
private Image<Rgba32> bmpCore;
19+
private MemoryStream destinationStream;
1920

2021
[GlobalSetup]
2122
public void ReadImages()
2223
{
2324
if (this.bmpStream == null)
2425
{
25-
const string TestImage = TestImages.Bmp.NegHeight;
26+
const string TestImage = TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr;
2627
this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage));
2728
this.bmpCore = Image.Load<Rgba32>(this.bmpStream);
29+
this.bmpCore.Metadata.ExifProfile = null;
2830
this.bmpStream.Position = 0;
2931
this.bmpDrawing = SDImage.FromStream(this.bmpStream);
32+
this.destinationStream = new MemoryStream();
3033
}
3134
}
3235

@@ -42,15 +45,15 @@ public void Cleanup()
4245
[Benchmark(Baseline = true, Description = "System.Drawing Jpeg")]
4346
public void JpegSystemDrawing()
4447
{
45-
using var stream = new MemoryStream();
46-
this.bmpDrawing.Save(stream, ImageFormat.Jpeg);
48+
this.bmpDrawing.Save(this.destinationStream, ImageFormat.Jpeg);
49+
this.destinationStream.Seek(0, SeekOrigin.Begin);
4750
}
4851

4952
[Benchmark(Description = "ImageSharp Jpeg")]
5053
public void JpegCore()
5154
{
52-
using var stream = new MemoryStream();
53-
this.bmpCore.SaveAsJpeg(stream);
55+
this.bmpCore.SaveAsJpeg(this.destinationStream);
56+
this.destinationStream.Seek(0, SeekOrigin.Begin);
5457
}
5558
}
5659
}

tests/ImageSharp.Tests.ProfilingSandbox/Program.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,21 @@ private class ConsoleOutput : ITestOutputHelper
3131
/// </param>
3232
public static void Main(string[] args)
3333
{
34+
RunJpegEncoderProfilingTests();
3435
// RunJpegColorProfilingTests();
35-
RunDecodeJpegProfilingTests();
36+
// RunDecodeJpegProfilingTests();
3637
// RunToVector4ProfilingTest();
3738
// RunResizeProfilingTest();
3839

3940
Console.ReadLine();
4041
}
4142

43+
private static void RunJpegEncoderProfilingTests()
44+
{
45+
var benchmarks = new JpegProfilingBenchmarks(new ConsoleOutput());
46+
benchmarks.EncodeJpeg_SingleMidSize();
47+
}
48+
4249
private static void RunJpegColorProfilingTests()
4350
{
4451
new JpegColorConverterTests(new ConsoleOutput()).BenchmarkYCbCr(false);

tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ private void DecodeJpegBenchmarkImpl(string fileName, IImageDecoder decoder, int
7575
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
7676
}
7777

78+
[Fact(Skip = ProfilingSetup.SkipProfilingTests)]
79+
public void EncodeJpeg_SingleMidSize()
80+
{
81+
string path = TestFile.GetInputFileFullPath(TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr);
82+
using var image = Image.Load(path);
83+
image.Metadata.ExifProfile = null;
84+
85+
using var ms = new MemoryStream();
86+
for (int i = 0; i < 30; i++)
87+
{
88+
image.SaveAsJpeg(ms);
89+
ms.Seek(0, SeekOrigin.Begin);
90+
}
91+
}
92+
7893
// Benchmark, enable manually!
7994
[Theory(Skip = ProfilingSetup.SkipProfilingTests)]
8095
[InlineData(1, 75, JpegSubsample.Ratio420)]

0 commit comments

Comments
 (0)