Conversation
95a77a8 to
d0baa16
Compare
There was a problem hiding this comment.
Pull request overview
This pull request fixes a critical performance regression in async 7z extraction (issue #1199) by implementing proper stream reuse for solid archives, similar to the sync fix in PR #1172. Additionally, it includes extensive code quality improvements across the codebase.
Changes:
- Fixed SevenZipReader to maintain folder stream state and reuse decompression streams across entries in solid archives, preventing recreation of streams that breaks sequential reading
- Enhanced Dispose/DisposeAsync patterns across numerous stream classes to properly call base class disposal methods
- Improved exception types for better error semantics (Exception → InvalidDataException/InvalidOperationException)
- Relaxed several high-volume code analyzers from error to suggestion severity to facilitate incremental improvements
- Added culture-invariant string operations in build scripts for consistent cross-locale behavior
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs | Added tests to verify solid archive stream reuse behavior |
| src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs | Implemented folder stream caching in SevenZipReader; removed SyncOnlyStream wrapper; async delegates to sync |
| src/SharpCompress/IO/SharpCompressStream.Async.cs | Added base.DisposeAsync() call |
| src/SharpCompress/Compressors/ZStandard/*.cs | Fixed Dispose/DisposeAsync to call base class methods |
| src/SharpCompress/Compressors/Xz/XZStream.cs | Removed unused field and simplified constructor |
| src/SharpCompress/Compressors/Xz/XZBlock.cs | Removed unused _checkType field |
| src/SharpCompress/Compressors/Squeezed/SqueezedStream.cs | Removed unused _compressedSize field |
| src/SharpCompress/Compressors/Shrink/ShrinkStream.cs | Removed unused _compressionMode field |
| src/SharpCompress/Compressors/Shrink/BitStream.cs | Simplified unnecessary type casts |
| src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs | Removed unused dummy field |
| src/SharpCompress/Compressors/RLE90/RunLength90Stream*.cs | Added parameter names to ArgumentOutOfRangeException; fixed Dispose pattern |
| src/SharpCompress/Compressors/Lzw/LzwStream.cs | Added base.Dispose() call |
| src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs | Removed unused constants and method |
| src/SharpCompress/Compressors/LZMA/LZipStream.cs | Fixed Dispose pattern to call base |
| src/SharpCompress/Compressors/Filters/DeltaFilter.cs | Removed unused DISTANCE_MIN constant |
| src/SharpCompress/Compressors/Explode/ExplodeStream*.cs | Changed Exception to InvalidDataException; added System.IO.Compression using |
| src/SharpCompress/Compressors/BZip2/*.cs | Fixed Dispose pattern |
| src/SharpCompress/Compressors/Arj/LhaStream*.cs | Changed Exception to InvalidDataException; added parameter name to ArgumentOutOfRangeException; removed unused field |
| src/SharpCompress/Common/Zip/WinzipAesCryptoStream*.cs | Fixed Dispose/DisposeAsync patterns |
| src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs | Removed unused field; fixed Dispose/DisposeAsync patterns |
| src/SharpCompress/Common/Tar/Headers/TarHeader*.cs | Changed Exception types to InvalidOperationException/InvalidDataException |
| src/SharpCompress/Common/Rar/Headers/*.cs | Changed HostOs reads to discard; removed unused properties |
| src/SharpCompress/Common/Arj/Headers/*.cs | Removed unused constants |
| src/SharpCompress/Archives/Zip/ZipArchive*.cs | Removed unnecessary option conversion in SaveTo |
| src/SharpCompress/Archives/Tar/TarArchive*.cs | Removed unnecessary option conversion in SaveTo |
| src/SharpCompress/Archives/GZip/GZipArchive*.cs | Removed unnecessary option conversion in SaveTo |
| build/Program.cs | Added CultureInfo.InvariantCulture for ToLower/ToUpper/Contains; improved robustness with early returns |
| Directory.Build.props | Re-enabled analyzers by removing False settings |
| .editorconfig | Downgraded high-volume analyzers from error to suggestion |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Extract the entry to trigger GetEntryStream | ||
| using var entryStream = await reader.OpenEntryStreamAsync(); | ||
| var buffer = new byte[4096]; | ||
| while (entryStream.Read(buffer, 0, buffer.Length) > 0) |
There was a problem hiding this comment.
The test is using synchronous Read() instead of ReadAsync(). For an async test, this should use await entryStream.ReadAsync(buffer, 0, buffer.Length) to properly exercise the async code path. The current implementation may not fully test the async behavior that the test is designed to verify.
| while (entryStream.Read(buffer, 0, buffer.Length) > 0) | |
| int bytesRead; | |
| while ((bytesRead = await entryStream.ReadAsync(buffer, 0, buffer.Length)) > 0) |
| var buffer = new byte[4096]; | ||
| while (entryStream.Read(buffer, 0, buffer.Length) > 0) | ||
| { | ||
| // Read the stream to completion | ||
| } |
There was a problem hiding this comment.
Empty block without comment.
| var buffer = new byte[4096]; | |
| while (entryStream.Read(buffer, 0, buffer.Length) > 0) | |
| { | |
| // Read the stream to completion | |
| } | |
| // Read the stream to completion to exercise folder stream reuse behavior | |
| await entryStream.CopyToAsync(Stream.Null); |
| // Read the stream to completion | ||
| } | ||
|
|
||
| entryCount++; |
There was a problem hiding this comment.
This assignment to entryCount is useless, since its value is never read.
Async version of #1172
Reported #1199
This pull request improves the async extraction support for 7z (SevenZip) archives, particularly solid archives, and adds new tests to ensure correct stream reuse and contiguous extraction. The main focus is on ensuring that, during extraction from solid archives, the decompression stream is reused for entries in the same folder, which is critical for performance and correctness.
Key changes include:
SevenZip Archive Extraction Improvements:
GetEntryStreamAsynctoSevenZipArchive, enabling proper asynchronous extraction support and aligning with the sync method.Testing and Verification: