Browse Source

Pool buffer

af/merge-core
James Jackson-South 8 years ago
parent
commit
01ab0d16ec
  1. 18
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/DoubleBufferedStreamReader.cs
  2. 4
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
  3. 73
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs
  4. 53
      tests/ImageSharp.Benchmarks/General/DoubleBufferedStreams.cs

18
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/DoubleBufferedStreamReader.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Memory;
// TODO: This could be useful elsewhere.
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
@ -11,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// A stream reader that add a secondary level buffer in addition to native stream buffered reading
/// to reduce the overhead of small incremental reads.
/// </summary>
internal class DoubleBufferedStreamReader
internal class DoubleBufferedStreamReader : IDisposable
{
/// <summary>
/// The length, in bytes, of the chunk
@ -20,6 +21,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
private readonly Stream stream;
private readonly IManagedByteBuffer buffer;
private readonly byte[] chunk;
private int bytesRead;
@ -29,14 +32,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// <summary>
/// Initializes a new instance of the <see cref="DoubleBufferedStreamReader"/> class.
/// </summary>
/// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
/// <param name="stream">The input stream.</param>
public DoubleBufferedStreamReader(Stream stream)
public DoubleBufferedStreamReader(MemoryManager memoryManager, Stream stream)
{
this.stream = stream;
this.Length = stream.Length;
// TODO: Consider pooling this.
this.chunk = new byte[ChunkLength];
this.buffer = memoryManager.AllocateCleanManagedByteBuffer(ChunkLength);
this.chunk = this.buffer.Array;
}
/// <summary>
@ -147,5 +151,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return Math.Max(n, 0);
}
/// <inheritdoc/>
public void Dispose()
{
this.buffer?.Dispose();
}
}
}

4
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
public void ParseStream(Stream stream, bool metadataOnly = false)
{
this.MetaData = new ImageMetaData();
this.InputStream = new DoubleBufferedStreamReader(stream);
this.InputStream = new DoubleBufferedStreamReader(this.configuration.MemoryManager, stream);
// Check for the Start Of Image marker.
this.InputStream.Read(this.markerBuffer, 0, 2);
@ -339,9 +339,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// <inheritdoc/>
public void Dispose()
{
this.InputStream?.Dispose();
this.Frame?.Dispose();
// Set large fields to null.
this.InputStream = null;
this.Frame = null;
this.dcHuffmanTables = null;
this.acHuffmanTables = null;

73
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs

@ -0,0 +1,73 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
public class DoubleBufferedStreams
{
private byte[] buffer = CreateTestBytes();
private MemoryStream stream1;
private MemoryStream stream2;
DoubleBufferedStreamReader reader;
[GlobalSetup]
public void CreateStreams()
{
this.stream1 = new MemoryStream(this.buffer);
this.stream2 = new MemoryStream(this.buffer);
this.reader = new DoubleBufferedStreamReader(Configuration.Default.MemoryManager, this.stream2);
}
[GlobalCleanup]
public void DestroyStreams()
{
this.stream1?.Dispose();
this.stream2?.Dispose();
this.reader?.Dispose();
}
[Benchmark(Baseline = true)]
public int StandardStream()
{
int r = 0;
Stream stream = this.stream1;
for (int i = 0; i < stream.Length; i++)
{
r += stream.ReadByte();
}
return r;
}
[Benchmark]
public int DoubleBufferedStream()
{
int r = 0;
DoubleBufferedStreamReader reader = this.reader;
for (int i = 0; i < reader.Length; i++)
{
r += reader.ReadByte();
}
return r;
}
private static byte[] CreateTestBytes()
{
byte[] buffer = new byte[DoubleBufferedStreamReader.ChunkLength * 3];
var random = new Random();
random.NextBytes(buffer);
return buffer;
}
}
}

53
tests/ImageSharp.Benchmarks/General/DoubleBufferedStreams.cs

@ -1,53 +0,0 @@
using System;
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components;
namespace SixLabors.ImageSharp.Benchmarks.General
{
[Config(typeof(Config.ShortClr))]
public class DoubleBufferedStreams
{
private byte[] buffer = CreateTestBytes();
[Benchmark]
public int StandardStream()
{
int r = 0;
using (var stream = new MemoryStream(this.buffer))
{
for (int i = 0; i < stream.Length; i++)
{
r += stream.ReadByte();
}
}
return r;
}
[Benchmark]
public int ChunkedStream()
{
int r = 0;
using (var stream = new MemoryStream(this.buffer))
{
var reader = new DoubleBufferedStreamReader(stream);
for (int i = 0; i < reader.Length; i++)
{
r += reader.ReadByte();
}
}
return r;
}
private static byte[] CreateTestBytes()
{
byte[] buffer = new byte[DoubleBufferedStreamReader.ChunkLength * 3];
var random = new Random();
random.NextBytes(buffer);
return buffer;
}
}
}
Loading…
Cancel
Save