From 43579dfb39482be0d574e32f97922f069aa17603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Tue, 18 Dec 2018 01:19:21 +0100 Subject: [PATCH] Revert Adler32 changes and add test --- .../Checksum/Adler32.cs | 25 +++++++++++++++-- .../Checksum/ChecksumTests.cs | 28 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs b/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs index 2684b642c..b2a0f151a 100644 --- a/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs +++ b/src/ICSharpCode.SharpZipLib/Checksum/Adler32.cs @@ -133,10 +133,31 @@ public void Update(byte[] buffer) /// public void Update(ArraySegment segment) { - foreach (byte b in segment) + //(By Per Bothner) + uint s1 = checkValue & 0xFFFF; + uint s2 = checkValue >> 16; + var count = segment.Count; + var offset = segment.Offset; + while (count > 0) { - Update(b); + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > count) + { + n = count; + } + count -= n; + while (--n >= 0) + { + s1 = s1 + (uint)(segment.Array[offset++] & 0xff); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; } + checkValue = (s2 << 16) | s1; } } } diff --git a/test/ICSharpCode.SharpZipLib.Tests/Checksum/ChecksumTests.cs b/test/ICSharpCode.SharpZipLib.Tests/Checksum/ChecksumTests.cs index 4ad315c1e..b8aefc52f 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Checksum/ChecksumTests.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Checksum/ChecksumTests.cs @@ -1,6 +1,7 @@ using ICSharpCode.SharpZipLib.Checksum; using NUnit.Framework; using System; +using System.Diagnostics; namespace ICSharpCode.SharpZipLib.Tests.Checksum { @@ -27,6 +28,33 @@ public void Adler_32() exceptionTesting(underTestAdler32); } + const long BufferSize = 256 * 1024 * 1024; + + [Test] + public void Adler_32_Performance() + { + var rand = new Random(1); + + var buffer = new byte[BufferSize]; + rand.NextBytes(buffer); + + var adler = new Adler32(); + Assert.AreEqual(0x00000001, adler.Value); + + var sw = new Stopwatch(); + sw.Start(); + + adler.Update(buffer); + + sw.Stop(); + Console.WriteLine($"Adler32 Hashing of 256 MiB: {sw.Elapsed.TotalSeconds:f4} second(s)"); + + adler.Update(check); + Assert.AreEqual(0xD4897DA3, adler.Value); + + exceptionTesting(adler); + } + [Test] public void CRC_32_BZip2() {