From d6bf9dae420d8a8f1c8221b505081e7c14806fb6 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:01:09 -0700 Subject: [PATCH 01/13] Eliminate allocation --- src/SharpCompress/Common/Tar/Headers/TarHeader.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 80c4a9337..b04b0b2c8 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -7,7 +7,7 @@ namespace SharpCompress.Common.Tar.Headers { - internal class TarHeader + internal sealed class TarHeader { internal static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); @@ -260,10 +260,16 @@ private static long ReadAsciiInt64(byte[] buffer, int offset, int count) return Convert.ToInt64(s); } + + private static readonly byte[] eightSpaces = { + (byte)' ', (byte)' ', (byte)' ', (byte)' ', + (byte)' ', (byte)' ', (byte)' ', (byte)' ' + }; + internal static int RecalculateChecksum(byte[] buf) { // Set default value for checksum. That is 8 spaces. - Encoding.UTF8.GetBytes(" ").CopyTo(buf, 148); + eightSpaces.CopyTo(buf, 148); // Calculate checksum int headerChecksum = 0; @@ -276,7 +282,7 @@ internal static int RecalculateChecksum(byte[] buf) internal static int RecalculateAltChecksum(byte[] buf) { - Encoding.UTF8.GetBytes(" ").CopyTo(buf, 148); + eightSpaces.CopyTo(buf, 148); int headerChecksum = 0; foreach (byte b in buf) { From 40af9359db56a64744883015c9253b3ef554785e Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:08:38 -0700 Subject: [PATCH 02/13] Pollyfill and use Stream.Read(Span buffer) --- src/SharpCompress/Common/GZip/GZipFilePart.cs | 12 ++++++------ .../Compressors/Deflate/ZlibBaseStream.cs | 10 +++++----- .../Polyfills/StreamExtensions.cs | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/SharpCompress/Common/GZip/GZipFilePart.cs b/src/SharpCompress/Common/GZip/GZipFilePart.cs index 40b5f01d9..2ac205e15 100644 --- a/src/SharpCompress/Common/GZip/GZipFilePart.cs +++ b/src/SharpCompress/Common/GZip/GZipFilePart.cs @@ -8,7 +8,7 @@ namespace SharpCompress.Common.GZip { - internal class GZipFilePart : FilePart + internal sealed class GZipFilePart : FilePart { private string? _name; private readonly Stream _stream; @@ -40,8 +40,8 @@ internal override Stream GetRawStream() private void ReadAndValidateGzipHeader(Stream stream) { // read the header on the first read - byte[] header = new byte[10]; - int n = stream.Read(header, 0, header.Length); + Span header = stackalloc byte[10]; + int n = stream.Read(header); // workitem 8501: handle edge case (decompress empty stream) if (n == 0) @@ -59,14 +59,14 @@ private void ReadAndValidateGzipHeader(Stream stream) throw new ZlibException("Bad GZIP header."); } - int timet = BinaryPrimitives.ReadInt32LittleEndian(header.AsSpan(4)); + int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4)); DateModified = TarHeader.EPOCH.AddSeconds(timet); if ((header[3] & 0x04) == 0x04) { // read and discard extra field - n = stream.Read(header, 0, 2); // 2-byte length field + n = stream.Read(header.Slice(0, 2)); // 2-byte length field - Int16 extraLength = (Int16)(header[0] + header[1] * 256); + short extraLength = (short)(header[0] + header[1] * 256); byte[] extra = new byte[extraLength]; if (!stream.ReadFully(extra)) diff --git a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs index 788f1ba76..564d15db4 100644 --- a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs +++ b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs @@ -413,8 +413,8 @@ private int _ReadAndValidateGzipHeader() int totalBytesRead = 0; // read the header on the first read - byte[] header = new byte[10]; - int n = _stream.Read(header, 0, header.Length); + Span header = stackalloc byte[10]; + int n = _stream.Read(header); // workitem 8501: handle edge case (decompress empty stream) if (n == 0) @@ -432,16 +432,16 @@ private int _ReadAndValidateGzipHeader() throw new ZlibException("Bad GZIP header."); } - Int32 timet = BinaryPrimitives.ReadInt32LittleEndian(header.AsSpan(4)); + int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4)); _GzipMtime = TarHeader.EPOCH.AddSeconds(timet); totalBytesRead += n; if ((header[3] & 0x04) == 0x04) { // read and discard extra field - n = _stream.Read(header, 0, 2); // 2-byte length field + n = _stream.Read(header.Slice(0, 2)); // 2-byte length field totalBytesRead += n; - Int16 extraLength = (Int16)(header[0] + header[1] * 256); + short extraLength = (short)(header[0] + header[1] * 256); byte[] extra = new byte[extraLength]; n = _stream.Read(extra, 0, extra.Length); if (n != extraLength) diff --git a/src/SharpCompress/Polyfills/StreamExtensions.cs b/src/SharpCompress/Polyfills/StreamExtensions.cs index cbb3ba323..be97c6391 100644 --- a/src/SharpCompress/Polyfills/StreamExtensions.cs +++ b/src/SharpCompress/Polyfills/StreamExtensions.cs @@ -6,6 +6,24 @@ namespace System.IO { public static class StreamExtensions { + public static int Read(this Stream stream, Span buffer) + { + byte[] temp = ArrayPool.Shared.Rent(buffer.Length); + + try + { + int read = stream.Read(temp, 0, buffer.Length); + + temp.AsSpan(0, read).CopyTo(buffer); + + return read; + } + finally + { + ArrayPool.Shared.Return(temp); + } + } + public static void Write(this Stream stream, ReadOnlySpan buffer) { byte[] temp = ArrayPool.Shared.Rent(buffer.Length); From 3b11e6ef97a9e0e80dd015576a64c3d3b57f513a Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:10:59 -0700 Subject: [PATCH 03/13] Eliminate two allocations --- src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs index 9559e9b48..89b5d904e 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs @@ -1,4 +1,5 @@ using System; + using SharpCompress.Compressors.Rar.VM; namespace SharpCompress.Compressors.Rar.UnpackV1 @@ -182,8 +183,8 @@ internal static int decodeNumber(this BitInput input, Decode.Decode dec) internal static void makeDecodeTables(byte[] lenTab, int offset, Decode.Decode dec, int size) { - int[] lenCount = new int[16]; - int[] tmpPos = new int[16]; + Span lenCount = stackalloc int[16]; + Span tmpPos = stackalloc int[16]; int i; long M, N; From c618eacad44431faf73ce2f08de6cf029ddc7d97 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:22:44 -0700 Subject: [PATCH 04/13] Optimize RijndaelEngine --- src/SharpCompress/Common/Rar/RarRijndael.cs | 6 ++-- src/SharpCompress/Crypto/IBlockCipher.cs | 8 +++--- src/SharpCompress/Crypto/RijndaelEngine.cs | 32 +++++++-------------- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/SharpCompress/Common/Rar/RarRijndael.cs b/src/SharpCompress/Common/Rar/RarRijndael.cs index 312cd79fb..6d09fe275 100644 --- a/src/SharpCompress/Common/Rar/RarRijndael.cs +++ b/src/SharpCompress/Common/Rar/RarRijndael.cs @@ -87,11 +87,11 @@ public static RarRijndael InitializeFrom(string password, byte[] salt) return rijndael; } - public byte[] ProcessBlock(byte[] cipherText) + public byte[] ProcessBlock(ReadOnlySpan cipherText) { - var plainText = new byte[CRYPTO_BLOCK_SIZE]; + Span plainText = stackalloc byte[CRYPTO_BLOCK_SIZE]; // 16 bytes byte[] decryptedBytes = new byte[CRYPTO_BLOCK_SIZE]; - _rijndael.ProcessBlock(cipherText, 0, plainText, 0); + _rijndael.ProcessBlock(cipherText, plainText); for (int j = 0; j < CRYPTO_BLOCK_SIZE; j++) { diff --git a/src/SharpCompress/Crypto/IBlockCipher.cs b/src/SharpCompress/Crypto/IBlockCipher.cs index 6f6542e30..61a37c46c 100644 --- a/src/SharpCompress/Crypto/IBlockCipher.cs +++ b/src/SharpCompress/Crypto/IBlockCipher.cs @@ -1,4 +1,6 @@ -namespace SharpCompress.Crypto +using System; + +namespace SharpCompress.Crypto { /// Base interface for a symmetric key block cipher. public interface IBlockCipher @@ -19,12 +21,10 @@ public interface IBlockCipher /// Process a block. /// The input buffer. - /// The offset into inBuf that the input block begins. /// The output buffer. - /// The offset into outBuf to write the output block. /// If input block is wrong size, or outBuf too small. /// The number of bytes processed and produced. - int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff); + int ProcessBlock(ReadOnlySpan inBuf, Span outBuf); /// /// Reset the cipher to the same state as it was after the last init (if there was one). diff --git a/src/SharpCompress/Crypto/RijndaelEngine.cs b/src/SharpCompress/Crypto/RijndaelEngine.cs index d49e06fdc..b1adaa763 100644 --- a/src/SharpCompress/Crypto/RijndaelEngine.cs +++ b/src/SharpCompress/Crypto/RijndaelEngine.cs @@ -214,8 +214,7 @@ public sealed class RijndaelEngine * xor corresponding text input and round key input bytes */ - private void KeyAddition( - long[] rk) + private void KeyAddition(long[] rk) { A0 ^= rk[0]; A1 ^= rk[1]; @@ -568,28 +567,24 @@ public int GetBlockSize() return BC / 2; } - public int ProcessBlock( - byte[] input, - int inOff, - byte[] output, - int outOff) + public int ProcessBlock(ReadOnlySpan input, Span output) { if (workingKey is null) { throw new InvalidOperationException("Rijndael engine not initialised"); } - if ((inOff + (BC / 2)) > input.Length) + if (BC / 2 > input.Length) { throw new DataLengthException("input buffer too short"); } - if ((outOff + (BC / 2)) > output.Length) + if (BC / 2 > output.Length) { throw new DataLengthException("output buffer too short"); } - UnPackBlock(input, inOff); + UnPackBlock(input); if (forEncryption) { @@ -600,7 +595,7 @@ public int GetBlockSize() DecryptBlock(workingKey); } - PackBlock(output, outOff); + PackBlock(output); return BC / 2; } @@ -609,11 +604,9 @@ public void Reset() { } - private void UnPackBlock( - byte[] bytes, - int off) + private void UnPackBlock(ReadOnlySpan bytes) { - int index = off; + int index = 0; A0 = bytes[index++] & 0xff; A1 = bytes[index++] & 0xff; @@ -629,11 +622,9 @@ public void Reset() } } - private void PackBlock( - byte[] bytes, - int off) + private void PackBlock(Span bytes) { - int index = off; + int index = 0; for (int j = 0; j != BC; j += 8) { @@ -644,8 +635,7 @@ public void Reset() } } - private void EncryptBlock( - long[][] rk) + private void EncryptBlock(long[][] rk) { int r; From 98ed3080d097ae97b5aca2626428d9d8a3700b58 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:30:09 -0700 Subject: [PATCH 05/13] Eliminate three allocations --- src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs | 4 ++-- src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs index d12b30b22..62c928abd 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs @@ -1,5 +1,6 @@ #nullable disable +using System; using System.IO; /* @@ -835,7 +836,7 @@ cache misses. private void SetupBlock() { - int[] cftab = new int[257]; + Span cftab = stackalloc int[257]; char ch; cftab[0] = 0; @@ -854,7 +855,6 @@ private void SetupBlock() tt[cftab[ch]] = i; cftab[ch]++; } - cftab = null; tPos = tt[origPtr]; diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs index 2a7b2ab2d..01d3af4c3 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; /* * Copyright 2001,2004-2005 The Apache Software Foundation @@ -1328,8 +1329,8 @@ private void QSort3(int loSt, int hiSt, int dSt) private void MainSort() { int i, j, ss, sb; - int[] runningOrder = new int[256]; - int[] copy = new int[256]; + Span runningOrder = stackalloc int[256]; + Span copy = stackalloc int[256]; bool[] bigDone = new bool[256]; int c1, c2; int numQSorted; From ae5635319bfcb4fe3d345971320398e4d0351319 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:30:26 -0700 Subject: [PATCH 06/13] Eliminate header bytes allocation --- src/SharpCompress/Compressors/LZMA/LZipStream.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index bf2e52651..c825c3bb0 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -168,9 +168,10 @@ public static int ValidateAndReadSize(Stream stream) { throw new ArgumentNullException(nameof(stream)); } + // Read the header - byte[] header = new byte[6]; - int n = stream.Read(header, 0, header.Length); + Span header = stackalloc byte[6]; + int n = stream.Read(header); // TODO: Handle reading only part of the header? From 75a6db8f4c025c1d62bf03ea79f3d893ac711a45 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:33:00 -0700 Subject: [PATCH 07/13] Eliminate three allocations in HbMakeCodeLengths --- src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs index 01d3af4c3..a0e9705a0 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs @@ -89,9 +89,9 @@ private void MakeMaps() int nNodes, nHeap, n1, n2, i, j, k; bool tooLong; - int[] heap = new int[BZip2Constants.MAX_ALPHA_SIZE + 2]; - int[] weight = new int[BZip2Constants.MAX_ALPHA_SIZE * 2]; - int[] parent = new int[BZip2Constants.MAX_ALPHA_SIZE * 2]; + Span heap = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE + 2]; // 1040 bytes + Span weight = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE * 2]; // 1040 bytes + Span parent = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE * 2]; // 1040 bytes for (i = 0; i < alphaSize; i++) { From 5ddb0f96bc856d638aa99b388f741d4f9276a878 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:37:56 -0700 Subject: [PATCH 08/13] Use switch expressions --- src/SharpCompress/Compressors/ADC/ADCBase.cs | 32 ++++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/SharpCompress/Compressors/ADC/ADCBase.cs b/src/SharpCompress/Compressors/ADC/ADCBase.cs index 62e008499..f8241b2f3 100644 --- a/src/SharpCompress/Compressors/ADC/ADCBase.cs +++ b/src/SharpCompress/Compressors/ADC/ADCBase.cs @@ -52,32 +52,24 @@ private static int GetChunkType(byte byt) private static int GetChunkSize(byte byt) { - switch (GetChunkType(byt)) + return GetChunkType(byt) switch { - case PLAIN: - return (byt & 0x7F) + 1; - case TWO_BYTE: - return ((byt & 0x3F) >> 2) + 3; - case THREE_BYTE: - return (byt & 0x3F) + 4; - default: - return -1; - } + PLAIN => (byt & 0x7F) + 1, + TWO_BYTE => ((byt & 0x3F) >> 2) + 3, + THREE_BYTE => (byt & 0x3F) + 4, + _ => -1, + }; } private static int GetOffset(ReadOnlySpan chunk) { - switch (GetChunkType(chunk[0])) + return GetChunkType(chunk[0]) switch { - case PLAIN: - return 0; - case TWO_BYTE: - return ((chunk[0] & 0x03) << 8) + chunk[1]; - case THREE_BYTE: - return (chunk[1] << 8) + chunk[2]; - default: - return -1; - } + PLAIN => 0, + TWO_BYTE => ((chunk[0] & 0x03) << 8) + chunk[1], + THREE_BYTE => (chunk[1] << 8) + chunk[2], + _ => -1, + }; } /// From d4ccf733401fbe48311f0cfcacfb60362bb5d626 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:47:05 -0700 Subject: [PATCH 09/13] Embed FAST_ENCODER_TREE_STRUCTURE_DATA --- src/SharpCompress/Compressors/Deflate64/FastEncoderStatus.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Compressors/Deflate64/FastEncoderStatus.cs b/src/SharpCompress/Compressors/Deflate64/FastEncoderStatus.cs index 19c22c946..f5f26276e 100644 --- a/src/SharpCompress/Compressors/Deflate64/FastEncoderStatus.cs +++ b/src/SharpCompress/Compressors/Deflate64/FastEncoderStatus.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Diagnostics; namespace SharpCompress.Compressors.Deflate64 @@ -10,7 +11,7 @@ internal static class FastEncoderStatics { // static information for encoding, DO NOT MODIFY - internal static readonly byte[] FAST_ENCODER_TREE_STRUCTURE_DATA = + internal static ReadOnlySpan FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[] { 0xec,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca, 0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60, @@ -23,7 +24,7 @@ internal static class FastEncoderStatics 0x1f,0x3f }; - internal static readonly byte[] B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA = + internal static ReadOnlySpan B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[] { 0xed,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca, 0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60, From 62f7238796b339fa35ea4e0e383fbaf904edcd7d Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:49:34 -0700 Subject: [PATCH 10/13] Make CMethodId readonly --- src/SharpCompress/Common/SevenZip/CMethodId.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Common/SevenZip/CMethodId.cs b/src/SharpCompress/Common/SevenZip/CMethodId.cs index ee9e3bb34..03ce8df66 100644 --- a/src/SharpCompress/Common/SevenZip/CMethodId.cs +++ b/src/SharpCompress/Common/SevenZip/CMethodId.cs @@ -1,6 +1,6 @@ namespace SharpCompress.Common.SevenZip { - internal struct CMethodId + internal readonly struct CMethodId { public const ulong K_COPY_ID = 0; public const ulong K_LZMA_ID = 0x030101; @@ -26,7 +26,7 @@ public override int GetHashCode() public override bool Equals(object obj) { - return obj is CMethodId && (CMethodId)obj == this; + return obj is CMethodId other && Equals(other); } public bool Equals(CMethodId other) From fa1e77396017c7b69b5ad86aa3b6b752e652c59d Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:55:07 -0700 Subject: [PATCH 11/13] Eliminate two allocations in Crc32 --- src/SharpCompress/Compressors/Deflate/CRC32.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/Compressors/Deflate/CRC32.cs b/src/SharpCompress/Compressors/Deflate/CRC32.cs index d1596e12f..d5e650c0c 100644 --- a/src/SharpCompress/Compressors/Deflate/CRC32.cs +++ b/src/SharpCompress/Compressors/Deflate/CRC32.cs @@ -189,7 +189,7 @@ public void SlurpBlock(byte[] block, int offset, int count) // pre-initialize the crc table for speed of lookup. - private uint gf2_matrix_times(uint[] matrix, uint vec) + private uint gf2_matrix_times(ReadOnlySpan matrix, uint vec) { uint sum = 0; int i = 0; @@ -205,7 +205,7 @@ private uint gf2_matrix_times(uint[] matrix, uint vec) return sum; } - private void gf2_matrix_square(uint[] square, uint[] mat) + private void gf2_matrix_square(Span square, Span mat) { for (int i = 0; i < 32; i++) { @@ -225,8 +225,8 @@ private void gf2_matrix_square(uint[] square, uint[] mat) /// the length of data the CRC value was calculated on public void Combine(int crc, int length) { - var even = new uint[32]; // even-power-of-two zeros operator - var odd = new uint[32]; // odd-power-of-two zeros operator + Span even = stackalloc uint[32]; // even-power-of-two zeros operator + Span odd = stackalloc uint[32]; // odd-power-of-two zeros operator if (length == 0) { From a649c25a916b2d4331f91c832c5ab4df3a730cc7 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 16:58:21 -0700 Subject: [PATCH 12/13] Eliminate two allocations in HuffmanTree --- src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs index 8741930c4..017c1cb95 100644 --- a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs +++ b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Diagnostics; using System.IO; @@ -118,14 +119,14 @@ private static byte[] GetStaticDistanceTreeLength() // This algorithm is described in standard RFC 1951 private uint[] CalculateHuffmanCode() { - uint[] bitLengthCount = new uint[17]; + Span bitLengthCount = stackalloc uint[17]; foreach (int codeLength in _codeLengthArray) { bitLengthCount[codeLength]++; } bitLengthCount[0] = 0; // clear count for length 0 - uint[] nextCode = new uint[17]; + Span nextCode = stackalloc uint[17]; uint tempCode = 0; for (int bits = 1; bits <= 16; bits++) { From 33ffcb9308104d87b31b4d49b184ba79442dc8b0 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 31 Jul 2020 17:00:46 -0700 Subject: [PATCH 13/13] Use Array.Empty --- src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs index 84a57e9d2..f525622b6 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; +using System; // TODO: REMOVE THIS... WIP #pragma warning disable 169 @@ -271,8 +272,8 @@ internal partial class Unpack byte *ReadBufMT; #endif - private byte[] FilterSrcMemory = new byte[0]; - private byte[] FilterDstMemory = new byte[0]; + private byte[] FilterSrcMemory = Array.Empty(); + private byte[] FilterDstMemory = Array.Empty(); // Filters code, one entry per filter. private readonly List Filters = new List();