revert BSS

This commit is contained in:
Adam Hathcock
2026-01-20 17:49:12 +00:00
parent af555c0096
commit c2c4387f59
5 changed files with 57 additions and 149 deletions

View File

@@ -18,10 +18,6 @@ namespace SharpCompress.Common
{
_originalStream = stream ?? throw new ArgumentNullException(nameof(stream));
_leaveOpen = leaveOpen;
// Use the stream directly without wrapping in BufferedStream
// BufferedStream uses synchronous Read internally which doesn't work with async-only streams
// SharpCompress uses SharpCompressStream for buffering which supports true async reads
_stream = stream;
}

View File

@@ -1,47 +1,18 @@
using System;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.IO;
internal class BufferedSubStream : SharpCompressStream, IStreamStack
internal class BufferedSubStream(Stream stream, long origin, long bytesToRead)
: SharpCompressStream(stream, throwOnDispose: false)
{
#if DEBUG_STREAMS
long IStreamStack.InstanceId { get; set; }
#endif
Stream IStreamStack.BaseStream() => base.Stream;
public BufferedSubStream(Stream stream, long origin, long bytesToRead)
: base(stream, leaveOpen: true, throwOnDispose: false)
{
#if DEBUG_STREAMS
this.DebugConstruct(typeof(BufferedSubStream));
#endif
this.origin = origin;
this.BytesLeftToRead = bytesToRead;
}
protected override void Dispose(bool disposing)
{
#if DEBUG_STREAMS
this.DebugDispose(typeof(BufferedSubStream));
#endif
if (disposing)
{
ArrayPool<byte>.Shared.Return(_cache);
}
base.Dispose(disposing);
}
private int _cacheOffset;
private int _cacheLength;
private readonly byte[] _cache = ArrayPool<byte>.Shared.Rent(32 << 10);
private long origin;
private long BytesLeftToRead { get; set; }
private readonly byte[] _cache = ArrayPool<byte>.Shared.Rent(32 << 10);
private long BytesLeftToRead { get; set; } = bytesToRead;
public override bool CanRead => true;
@@ -51,7 +22,7 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack
public override void Flush() { }
public override long Length => BytesLeftToRead + _cacheLength - _cacheOffset;
public override long Length => BytesLeftToRead;
public override long Position
{
@@ -59,55 +30,32 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack
set => throw new NotSupportedException();
}
private void RefillCache()
{
var count = (int)Math.Min(BytesLeftToRead, _cache.Length);
_cacheOffset = 0;
if (count == 0)
{
_cacheLength = 0;
return;
}
Stream.Position = origin;
_cacheLength = Stream.Read(_cache, 0, count);
origin += _cacheLength;
BytesLeftToRead -= _cacheLength;
}
private async ValueTask RefillCacheAsync(CancellationToken cancellationToken)
{
var count = (int)Math.Min(BytesLeftToRead, _cache.Length);
_cacheOffset = 0;
if (count == 0)
{
_cacheLength = 0;
return;
}
Stream.Position = origin;
_cacheLength = await Stream
.ReadAsync(_cache, 0, count, cancellationToken)
.ConfigureAwait(false);
origin += _cacheLength;
BytesLeftToRead -= _cacheLength;
}
public override int Read(byte[] buffer, int offset, int count)
{
if (count > Length)
if (count > BytesLeftToRead)
{
count = (int)Length;
count = (int)BytesLeftToRead;
}
if (count > 0)
{
if (_cacheOffset == _cacheLength)
if (_cacheLength == 0)
{
RefillCache();
_cacheOffset = 0;
Stream.Position = origin;
_cacheLength = Stream.Read(_cache, 0, _cache.Length);
origin += _cacheLength;
}
if (count > _cacheLength)
{
count = _cacheLength;
}
count = Math.Min(count, _cacheLength - _cacheOffset);
Buffer.BlockCopy(_cache, _cacheOffset, buffer, offset, count);
_cacheOffset += count;
_cacheLength -= count;
BytesLeftToRead -= count;
}
return count;
@@ -115,77 +63,41 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack
public override int ReadByte()
{
if (_cacheOffset == _cacheLength)
if (BytesLeftToRead == 0)
{
RefillCache();
if (_cacheLength == 0)
{
return -1;
}
return -1;
}
return _cache[_cacheOffset++];
if (_cacheLength == 0)
{
_cacheOffset = 0;
Stream.Position = origin;
_cacheLength = Stream.Read(_cache, 0, _cache.Length);
origin += _cacheLength;
}
int value = _cache[_cacheOffset];
_cacheOffset++;
_cacheLength--;
BytesLeftToRead--;
return value;
}
public override async Task<int> ReadAsync(
byte[] buffer,
int offset,
int count,
CancellationToken cancellationToken
)
{
if (count > Length)
{
count = (int)Length;
}
if (count > 0)
{
if (_cacheOffset == _cacheLength)
{
await RefillCacheAsync(cancellationToken).ConfigureAwait(false);
}
count = Math.Min(count, _cacheLength - _cacheOffset);
Buffer.BlockCopy(_cache, _cacheOffset, buffer, offset, count);
_cacheOffset += count;
}
return count;
}
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
)
{
var count = buffer.Length;
if (count > Length)
{
count = (int)Length;
}
if (count > 0)
{
if (_cacheOffset == _cacheLength)
{
await RefillCacheAsync(cancellationToken).ConfigureAwait(false);
}
count = Math.Min(count, _cacheLength - _cacheOffset);
_cache.AsSpan(_cacheOffset, count).CopyTo(buffer.Span);
_cacheOffset += count;
}
return count;
}
#endif
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) =>
throw new NotSupportedException();
protected override void Dispose(bool disposing)
{
if (disposing)
{
ArrayPool<byte>.Shared.Return(_cache);
}
base.Dispose(disposing);
}
}

View File

@@ -7,8 +7,8 @@ public class Benchmarks
string filename = $"/Users/adam/Downloads/original.7z";
[Benchmark]
public async Task SharpCompress_0_44_Original()
public void SharpCompress_0_44_Original()
{
await Extractor.GetFiles(filename);
Extractor.GetFiles(filename);
}
}

View File

@@ -9,7 +9,7 @@ public static class Extractor
{
private const char Delimiter = '/';
public static async Task<IEnumerable<string>> GetFiles(string filename)
public static IEnumerable<string> GetFiles(string filename)
{
IArchive? archive = null;
FileStream? fileStream = null;
@@ -37,9 +37,9 @@ public static class Extractor
if (entryKey is null)
continue;
await using EntryStream source = reader.OpenEntryStream();
await using MemoryStream memoryStream = new();
await source.CopyToAsync(memoryStream);
using EntryStream source = reader.OpenEntryStream();
using MemoryStream memoryStream = new();
source.CopyTo(memoryStream);
var data = memoryStream.ToArray();
var nameParts = entryKey.Split(Delimiter);
@@ -51,7 +51,7 @@ public static class Extractor
{
if (fileStream is not null)
{
await fileStream.DisposeAsync();
fileStream.Dispose();
}
archive?.Dispose();
}

View File

@@ -7,7 +7,7 @@ using SharpCompress.Archives;
using SharpCompress.Performance;
using SharpCompress.Readers;
using SharpCompress.Test;
/*
var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf(
"SharpCompress.Performance",
StringComparison.OrdinalIgnoreCase
@@ -23,12 +23,12 @@ using (var __ = JetbrainsProfiler.Cpu($"/Users/adam/git/temp"))
string filename = $"/Users/adam/Downloads/original.7z";
for (int i = 0; i < 10; i++)
{
await Extractor.GetFiles(filename);
Extractor.GetFiles(filename);
Console.WriteLine(i);
}
Console.WriteLine("Still running...");
}
await Task.Delay(500);
await Task.Delay(500);*/
//BenchmarkRunner.Run<Benchmarks>();
BenchmarkRunner.Run<Benchmarks>();