Browse Source

Minor hashing optimizations

af/merge-core
James Jackson-South 8 years ago
parent
commit
c15f2328ec
  1. 45
      src/ImageSharp/Formats/Png/Zlib/Adler32.cs
  2. 35
      src/ImageSharp/Formats/Png/Zlib/Crc32.cs
  3. 20
      tests/ImageSharp.Benchmarks/Image/DecodePng.cs

45
src/ImageSharp/Formats/Png/Zlib/Adler32.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
@ -74,9 +75,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
/// <inheritdoc/>
public long Value => this.checksum;
public long Value
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return this.checksum;
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
this.checksum = 1;
@ -88,6 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <param name="value">
/// The data value to add. The high byte of the int is ignored.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(int value)
{
// We could make a length 1 byte array and call update again, but I
@ -102,6 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer)
{
if (buffer == null)
@ -113,32 +124,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer, int offset, int count)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(offset), "cannot be negative");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "cannot be negative");
}
if (offset >= buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset), "not a valid index into buffer");
}
if (offset + count > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(count), "exceeds buffer size");
}
DebugGuard.NotNull(buffer, nameof(buffer));
DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
DebugGuard.MustBeLessThan(offset, buffer.Length, nameof(offset));
DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
// (By Per Bothner)
uint s1 = this.checksum & 0xFFFF;
@ -169,4 +162,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
this.checksum = (s2 << 16) | s1;
}
}
}
}

35
src/ImageSharp/Formats/Png/Zlib/Crc32.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
@ -108,18 +109,15 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <inheritdoc/>
public long Value
{
get
{
return this.crc;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.crc;
set
{
this.crc = (uint)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => this.crc = (uint)value;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
this.crc = 0;
@ -129,6 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// Updates the checksum with the given value.
/// </summary>
/// <param name="value">The byte is taken as the lower 8 bits of value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(int value)
{
this.crc ^= CrcSeed;
@ -137,6 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer)
{
if (buffer == null)
@ -148,22 +148,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer, int offset, int count)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "Count cannot be less than zero");
}
if (offset < 0 || offset + count > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
DebugGuard.NotNull(buffer, nameof(buffer));
DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
this.crc ^= CrcSeed;

20
tests/ImageSharp.Benchmarks/Image/DecodePng.cs

@ -10,29 +10,39 @@ namespace SixLabors.ImageSharp.Benchmarks.Image
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Tests;
using CoreImage = ImageSharp.Image;
using CoreSize = SixLabors.Primitives.Size;
[Config(typeof(Config.ShortClr))]
public class DecodePng : BenchmarkBase
{
private byte[] pngBytes;
private string TestImageFullPath => Path.Combine(
TestEnvironment.InputImagesDirectoryFullPath,
this.TestImage);
[Params(TestImages.Png.Splash)]
public string TestImage { get; set; }
[GlobalSetup]
public void ReadImages()
{
if (this.pngBytes == null)
{
this.pngBytes = File.ReadAllBytes("../ImageSharp.Tests/TestImages/Formats/Png/splash.png");
this.pngBytes = File.ReadAllBytes(this.TestImageFullPath);
}
}
[Benchmark(Baseline = true, Description = "System.Drawing Png")]
public Size PngSystemDrawing()
{
using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
using (var memoryStream = new MemoryStream(this.pngBytes))
{
using (Image image = Image.FromStream(memoryStream))
using (var image = Image.FromStream(memoryStream))
{
return image.Size;
}
@ -42,9 +52,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Image
[Benchmark(Description = "ImageSharp Png")]
public CoreSize PngCore()
{
using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
using (var memoryStream = new MemoryStream(this.pngBytes))
{
using (Image<Rgba32> image = CoreImage.Load<Rgba32>(memoryStream))
using (var image = CoreImage.Load<Rgba32>(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}

Loading…
Cancel
Save