Browse Source

better JpegEncoder profiling/benchmarks

pull/1554/head
Anton Firszov 5 years ago
parent
commit
1968d3724f
  1. 4
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  3. 13
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs
  4. 9
      tests/ImageSharp.Tests.ProfilingSandbox/Program.cs
  5. 15
      tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs

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

@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <returns>The float value at the specified index</returns> /// <returns>The float value at the specified index</returns>
public float this[int idx] public float this[int idx]
{ {
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get get
{ {
GuardBlockIndex(idx); GuardBlockIndex(idx);
@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
return Unsafe.Add(ref selfRef, idx); return Unsafe.Add(ref selfRef, idx);
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
set set
{ {
GuardBlockIndex(idx); GuardBlockIndex(idx);

6
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -315,7 +315,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="bits">The packed bits.</param> /// <param name="bits">The packed bits.</param>
/// <param name="count">The number of bits</param> /// <param name="count">The number of bits</param>
/// <param name="emitBufferBase">The reference to the emitBuffer.</param> /// <param name="emitBufferBase">The reference to the emitBuffer.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(InliningOptions.ShortMethod)]
private void Emit(uint bits, uint count, ref byte emitBufferBase) private void Emit(uint bits, uint count, ref byte emitBufferBase)
{ {
count += this.bitCount; count += this.bitCount;
@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="index">The index of the Huffman encoder</param> /// <param name="index">The index of the Huffman encoder</param>
/// <param name="value">The value to encode.</param> /// <param name="value">The value to encode.</param>
/// <param name="emitBufferBase">The reference to the emit buffer.</param> /// <param name="emitBufferBase">The reference to the emit buffer.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(InliningOptions.ShortMethod)]
private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase) private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase)
{ {
uint x = HuffmanLut.TheHuffmanLut[(int)index].Values[value]; uint x = HuffmanLut.TheHuffmanLut[(int)index].Values[value];
@ -370,7 +370,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="runLength">The number of copies to encode.</param> /// <param name="runLength">The number of copies to encode.</param>
/// <param name="value">The value to encode.</param> /// <param name="value">The value to encode.</param>
/// <param name="emitBufferBase">The reference to the emit buffer.</param> /// <param name="emitBufferBase">The reference to the emit buffer.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(InliningOptions.ShortMethod)]
private void EmitHuffRLE(HuffIndex index, int runLength, int value, ref byte emitBufferBase) private void EmitHuffRLE(HuffIndex index, int runLength, int value, ref byte emitBufferBase)
{ {
int a = value; int a = value;

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

@ -16,17 +16,20 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
private Stream bmpStream; private Stream bmpStream;
private SDImage bmpDrawing; private SDImage bmpDrawing;
private Image<Rgba32> bmpCore; private Image<Rgba32> bmpCore;
private MemoryStream destinationStream;
[GlobalSetup] [GlobalSetup]
public void ReadImages() public void ReadImages()
{ {
if (this.bmpStream == null) if (this.bmpStream == null)
{ {
const string TestImage = TestImages.Bmp.NegHeight; const string TestImage = TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr;
this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage));
this.bmpCore = Image.Load<Rgba32>(this.bmpStream); this.bmpCore = Image.Load<Rgba32>(this.bmpStream);
this.bmpCore.Metadata.ExifProfile = null;
this.bmpStream.Position = 0; this.bmpStream.Position = 0;
this.bmpDrawing = SDImage.FromStream(this.bmpStream); this.bmpDrawing = SDImage.FromStream(this.bmpStream);
this.destinationStream = new MemoryStream();
} }
} }
@ -42,15 +45,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] [Benchmark(Baseline = true, Description = "System.Drawing Jpeg")]
public void JpegSystemDrawing() public void JpegSystemDrawing()
{ {
using var stream = new MemoryStream(); this.bmpDrawing.Save(this.destinationStream, ImageFormat.Jpeg);
this.bmpDrawing.Save(stream, ImageFormat.Jpeg); this.destinationStream.Seek(0, SeekOrigin.Begin);
} }
[Benchmark(Description = "ImageSharp Jpeg")] [Benchmark(Description = "ImageSharp Jpeg")]
public void JpegCore() public void JpegCore()
{ {
using var stream = new MemoryStream(); this.bmpCore.SaveAsJpeg(this.destinationStream);
this.bmpCore.SaveAsJpeg(stream); this.destinationStream.Seek(0, SeekOrigin.Begin);
} }
} }
} }

9
tests/ImageSharp.Tests.ProfilingSandbox/Program.cs

@ -31,14 +31,21 @@ namespace SixLabors.ImageSharp.Tests.ProfilingSandbox
/// </param> /// </param>
public static void Main(string[] args) public static void Main(string[] args)
{ {
RunJpegEncoderProfilingTests();
// RunJpegColorProfilingTests(); // RunJpegColorProfilingTests();
RunDecodeJpegProfilingTests(); // RunDecodeJpegProfilingTests();
// RunToVector4ProfilingTest(); // RunToVector4ProfilingTest();
// RunResizeProfilingTest(); // RunResizeProfilingTest();
Console.ReadLine(); Console.ReadLine();
} }
private static void RunJpegEncoderProfilingTests()
{
var benchmarks = new JpegProfilingBenchmarks(new ConsoleOutput());
benchmarks.EncodeJpeg_SingleMidSize();
}
private static void RunJpegColorProfilingTests() private static void RunJpegColorProfilingTests()
{ {
new JpegColorConverterTests(new ConsoleOutput()).BenchmarkYCbCr(false); new JpegColorConverterTests(new ConsoleOutput()).BenchmarkYCbCr(false);

15
tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs

@ -75,6 +75,21 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line #pragma warning restore SA1515 // Single-line comment should be preceded by blank line
} }
[Fact(Skip = ProfilingSetup.SkipProfilingTests)]
public void EncodeJpeg_SingleMidSize()
{
string path = TestFile.GetInputFileFullPath(TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr);
using var image = Image.Load(path);
image.Metadata.ExifProfile = null;
using var ms = new MemoryStream();
for (int i = 0; i < 30; i++)
{
image.SaveAsJpeg(ms);
ms.Seek(0, SeekOrigin.Begin);
}
}
// Benchmark, enable manually! // Benchmark, enable manually!
[Theory(Skip = ProfilingSetup.SkipProfilingTests)] [Theory(Skip = ProfilingSetup.SkipProfilingTests)]
[InlineData(1, 75, JpegSubsample.Ratio420)] [InlineData(1, 75, JpegSubsample.Ratio420)]

Loading…
Cancel
Save