mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-08 18:16:30 +00:00
Add pooling for arrays for deflate
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate;
|
||||
@@ -120,22 +121,29 @@ public class CRC32
|
||||
{
|
||||
//UInt32 crc32Result;
|
||||
//crc32Result = 0xFFFFFFFF;
|
||||
var buffer = new byte[BUFFER_SIZE];
|
||||
var readSize = BUFFER_SIZE;
|
||||
|
||||
TotalBytesRead = 0;
|
||||
var count = input.Read(buffer, 0, readSize);
|
||||
output?.Write(buffer, 0, count);
|
||||
TotalBytesRead += count;
|
||||
while (count > 0)
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(BUFFER_SIZE);
|
||||
try
|
||||
{
|
||||
SlurpBlock(buffer, 0, count);
|
||||
count = input.Read(buffer, 0, readSize);
|
||||
var readSize = BUFFER_SIZE;
|
||||
|
||||
TotalBytesRead = 0;
|
||||
var count = input.Read(buffer, 0, readSize);
|
||||
output?.Write(buffer, 0, count);
|
||||
TotalBytesRead += count;
|
||||
}
|
||||
while (count > 0)
|
||||
{
|
||||
SlurpBlock(buffer, 0, count);
|
||||
count = input.Read(buffer, 0, readSize);
|
||||
output?.Write(buffer, 0, count);
|
||||
TotalBytesRead += count;
|
||||
}
|
||||
|
||||
return ~runningCrc32Result;
|
||||
return ~runningCrc32Result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer, clearArray: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using SharpCompress.Algorithms;
|
||||
using SharpCompress.Common;
|
||||
|
||||
@@ -1726,9 +1727,12 @@ internal sealed partial class DeflateManager
|
||||
hash_mask = hash_size - 1;
|
||||
hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
|
||||
|
||||
window = new byte[w_size * 2];
|
||||
prev = new short[w_size];
|
||||
head = new short[hash_size];
|
||||
window = ArrayPool<byte>.Shared.Rent(w_size * 2);
|
||||
prev = ArrayPool<short>.Shared.Rent(w_size);
|
||||
head = ArrayPool<short>.Shared.Rent(hash_size);
|
||||
Array.Clear(window, 0, w_size * 2);
|
||||
Array.Clear(prev, 0, w_size);
|
||||
Array.Clear(head, 0, hash_size);
|
||||
|
||||
// for memLevel==8, this will be 16384, 16k
|
||||
lit_bufsize = 1 << (memLevel + 6);
|
||||
@@ -1737,7 +1741,8 @@ internal sealed partial class DeflateManager
|
||||
// the output distance codes, and the output length codes (aka tree).
|
||||
// orig comment: This works just fine since the average
|
||||
// output size for (length,distance) codes is <= 24 bits.
|
||||
pending = new byte[lit_bufsize * 4];
|
||||
pending = ArrayPool<byte>.Shared.Rent(lit_bufsize * 4);
|
||||
Array.Clear(pending, 0, lit_bufsize * 4);
|
||||
_distanceOffset = lit_bufsize;
|
||||
_lengthOffset = (1 + 2) * lit_bufsize;
|
||||
|
||||
@@ -1776,20 +1781,46 @@ internal sealed partial class DeflateManager
|
||||
|
||||
internal int End()
|
||||
{
|
||||
var result = ZlibConstants.Z_OK;
|
||||
if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE)
|
||||
{
|
||||
return ZlibConstants.Z_STREAM_ERROR;
|
||||
result = ZlibConstants.Z_STREAM_ERROR;
|
||||
}
|
||||
else if (status == BUSY_STATE)
|
||||
{
|
||||
result = ZlibConstants.Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
// Deallocate in reverse order of allocations:
|
||||
pending = null;
|
||||
head = null;
|
||||
prev = null;
|
||||
window = null;
|
||||
ReturnBuffers();
|
||||
|
||||
// free
|
||||
// dstate=null;
|
||||
return status == BUSY_STATE ? ZlibConstants.Z_DATA_ERROR : ZlibConstants.Z_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ReturnBuffers()
|
||||
{
|
||||
if (pending is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(pending, clearArray: true);
|
||||
pending = null;
|
||||
}
|
||||
if (head is not null)
|
||||
{
|
||||
ArrayPool<short>.Shared.Return(head, clearArray: true);
|
||||
head = null;
|
||||
}
|
||||
if (prev is not null)
|
||||
{
|
||||
ArrayPool<short>.Shared.Return(prev, clearArray: true);
|
||||
prev = null;
|
||||
}
|
||||
if (window is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(window, clearArray: true);
|
||||
window = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDeflater() =>
|
||||
|
||||
@@ -124,7 +124,8 @@ internal sealed class InflateBlocks
|
||||
internal InflateBlocks(ZlibCodec codec, object checkfn, int w)
|
||||
{
|
||||
_codec = codec;
|
||||
hufts = new int[MANY * 3];
|
||||
hufts = ArrayPool<int>.Shared.Rent(MANY * 3);
|
||||
Array.Clear(hufts, 0, MANY * 3);
|
||||
window = MemoryPool<byte>.Shared.Rent(w);
|
||||
end = w;
|
||||
this.checkfn = checkfn;
|
||||
@@ -719,7 +720,11 @@ internal sealed class InflateBlocks
|
||||
Reset();
|
||||
window?.Dispose();
|
||||
window = null;
|
||||
hufts = null;
|
||||
if (hufts is not null)
|
||||
{
|
||||
ArrayPool<int>.Shared.Return(hufts, clearArray: true);
|
||||
hufts = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetDictionary(byte[] d, int start, int n)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -136,7 +137,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] workingBuffer => _workingBuffer ??= new byte[_bufferSize];
|
||||
private byte[] workingBuffer => _workingBuffer ??= ArrayPool<byte>.Shared.Rent(_bufferSize);
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
@@ -541,6 +542,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
finally
|
||||
{
|
||||
end();
|
||||
ReturnWorkingBuffer();
|
||||
if (!_leaveOpen)
|
||||
{
|
||||
_stream?.Dispose();
|
||||
@@ -575,6 +577,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
finally
|
||||
{
|
||||
end();
|
||||
ReturnWorkingBuffer();
|
||||
if (_stream != null)
|
||||
{
|
||||
if (!_leaveOpen)
|
||||
@@ -593,6 +596,17 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
}
|
||||
}
|
||||
|
||||
private void ReturnWorkingBuffer()
|
||||
{
|
||||
if (_workingBuffer is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayPool<byte>.Shared.Return(_workingBuffer, clearArray: true);
|
||||
_workingBuffer = null;
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
// Only flush the underlying stream when in write mode
|
||||
|
||||
@@ -612,10 +612,9 @@ internal sealed class ZlibCodec
|
||||
throw new ZlibException("No Deflate State!");
|
||||
}
|
||||
|
||||
// TODO: dinoch Tue, 03 Nov 2009 15:39 (test this)
|
||||
//int ret = dstate.End();
|
||||
_ = dstate.End();
|
||||
dstate = null;
|
||||
return ZlibConstants.Z_OK; //ret;
|
||||
return ZlibConstants.Z_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user