mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 13:34:59 +00:00
Compare commits
8 Commits
master
...
copilot/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c4b83e501 | ||
|
|
80ac10a5fe | ||
|
|
a92ce90252 | ||
|
|
e519f61f0f | ||
|
|
49f2271253 | ||
|
|
5b1d11bc1d | ||
|
|
aa3a40d968 | ||
|
|
6125654b2e |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -20,3 +20,7 @@ artifacts/
|
||||
|
||||
.DS_Store
|
||||
*.snupkg
|
||||
|
||||
# BenchmarkDotNet artifacts
|
||||
BenchmarkDotNet.Artifacts/
|
||||
**/BenchmarkDotNet.Artifacts/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
|
||||
<PackageVersion Include="Bullseye" Version="6.1.0" />
|
||||
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
|
||||
<PackageVersion Include="Glob" Version="1.1.9" />
|
||||
|
||||
@@ -216,9 +216,9 @@
|
||||
"net10.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.0.1, )",
|
||||
"resolved": "10.0.1",
|
||||
"contentHash": "ISahzLHsHY7vrwqr2p1YWZ+gsxoBRtH7gWRDK8fDUst9pp2He0GiesaqEfeX0V8QMCJM3eNEHGGpnIcPjFo2NQ=="
|
||||
"requested": "[10.0.0, )",
|
||||
"resolved": "10.0.0",
|
||||
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
|
||||
86
tests/SharpCompress.Performance/ArchiveReadBenchmarks.cs
Normal file
86
tests/SharpCompress.Performance/ArchiveReadBenchmarks.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Archives;
|
||||
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Benchmarks for Archive API operations across different formats.
|
||||
/// Archive API is used for random access to entries with seekable streams.
|
||||
/// </summary>
|
||||
[MemoryDiagnoser]
|
||||
public class ArchiveReadBenchmarks : BenchmarkBase
|
||||
{
|
||||
[Benchmark]
|
||||
public void ZipArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Zip.deflate.zip");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarGzArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar.gz");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarBz2ArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar.bz2");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SevenZipArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("7Zip.LZMA2.7z");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RarArchiveRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Rar.rar");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Archives;
|
||||
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Benchmarks comparing current code against a baseline.
|
||||
/// Use [Baseline] attribute to mark the reference benchmark.
|
||||
/// </summary>
|
||||
[MemoryDiagnoser]
|
||||
[RankColumn]
|
||||
public class BaselineComparisonBenchmarks : BenchmarkBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Baseline benchmark for Zip archive reading.
|
||||
/// This serves as the reference point for comparison.
|
||||
/// </summary>
|
||||
[Benchmark(Baseline = true)]
|
||||
public void ZipArchiveRead_Baseline()
|
||||
{
|
||||
var path = GetTestArchivePath("Zip.deflate.zip");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current implementation benchmark for Zip archive reading.
|
||||
/// BenchmarkDotNet will compare this against the baseline.
|
||||
/// </summary>
|
||||
[Benchmark]
|
||||
public void ZipArchiveRead_Current()
|
||||
{
|
||||
var path = GetTestArchivePath("Zip.deflate.zip");
|
||||
using var archive = ArchiveFactory.Open(path);
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var stream = entry.OpenEntryStream();
|
||||
stream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
tests/SharpCompress.Performance/BenchmarkBase.cs
Normal file
37
tests/SharpCompress.Performance/BenchmarkBase.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all benchmarks providing common setup for test archives path
|
||||
/// </summary>
|
||||
public class BenchmarkBase
|
||||
{
|
||||
protected readonly string TEST_ARCHIVES_PATH;
|
||||
|
||||
public BenchmarkBase()
|
||||
{
|
||||
var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf(
|
||||
"SharpCompress.Performance",
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Could not locate SharpCompress.Performance in the base directory path"
|
||||
);
|
||||
}
|
||||
|
||||
var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, index);
|
||||
var solutionBasePath =
|
||||
Path.GetDirectoryName(path)
|
||||
?? throw new InvalidOperationException("Could not determine solution base path");
|
||||
|
||||
TEST_ARCHIVES_PATH = Path.Combine(solutionBasePath, "TestArchives", "Archives");
|
||||
}
|
||||
|
||||
protected string GetTestArchivePath(string filename) =>
|
||||
Path.Combine(TEST_ARCHIVES_PATH, filename);
|
||||
}
|
||||
@@ -1,54 +1,16 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Performance;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Test;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Running;
|
||||
|
||||
var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf(
|
||||
"SharpCompress.Performance",
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
);
|
||||
var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, index);
|
||||
var SOLUTION_BASE_PATH = Path.GetDirectoryName(path) ?? throw new ArgumentNullException();
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
var TEST_ARCHIVES_PATH = Path.Combine(SOLUTION_BASE_PATH, "TestArchives", "Archives");
|
||||
|
||||
//using var _ = JetbrainsProfiler.Memory($"/Users/adam/temp/");
|
||||
using (var __ = JetbrainsProfiler.Cpu($"/Users/adam/temp/"))
|
||||
internal class Program
|
||||
{
|
||||
var testArchives = new[]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
"Rar.Audio_program.rar",
|
||||
// Run all benchmarks in the assembly
|
||||
var config = DefaultConfig.Instance;
|
||||
|
||||
//"64bitstream.zip.7z",
|
||||
//"TarWithSymlink.tar.gz"
|
||||
};
|
||||
var arcs = testArchives.Select(a => Path.Combine(TEST_ARCHIVES_PATH, a)).ToArray();
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
using var found = ArchiveFactory.Open(arcs[0]);
|
||||
foreach (var entry in found.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
Console.WriteLine($"Extracting {entry.Key}");
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
entryStream.CopyTo(Stream.Null);
|
||||
}
|
||||
/*using var found = ReaderFactory.Open(arcs[0]);
|
||||
while (found.MoveToNextEntry())
|
||||
{
|
||||
var entry = found.Entry;
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"Extracting {entry.Key}");
|
||||
found.WriteEntryTo(Stream.Null);
|
||||
}*/
|
||||
// BenchmarkRunner will find all classes with [Benchmark] attributes
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
|
||||
}
|
||||
|
||||
Console.WriteLine("Still running...");
|
||||
}
|
||||
await Task.Delay(500);
|
||||
|
||||
131
tests/SharpCompress.Performance/README.md
Normal file
131
tests/SharpCompress.Performance/README.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# SharpCompress Performance Benchmarks
|
||||
|
||||
This project uses [BenchmarkDotNet](https://benchmarkdotnet.org/) to measure and track performance of SharpCompress archive operations.
|
||||
|
||||
## Running Benchmarks
|
||||
|
||||
### Run All Benchmarks
|
||||
```bash
|
||||
cd tests/SharpCompress.Performance
|
||||
dotnet run -c Release
|
||||
```
|
||||
|
||||
### Run Specific Benchmark Classes
|
||||
```bash
|
||||
# Run only Archive API benchmarks
|
||||
dotnet run -c Release -- --filter "*ArchiveReadBenchmarks*"
|
||||
|
||||
# Run only Reader API benchmarks
|
||||
dotnet run -c Release -- --filter "*ReaderBenchmarks*"
|
||||
```
|
||||
|
||||
### Run Specific Benchmark Methods
|
||||
```bash
|
||||
# Run only Zip benchmarks
|
||||
dotnet run -c Release -- --filter "*Zip*"
|
||||
|
||||
# Run a specific method
|
||||
dotnet run -c Release -- --filter "ArchiveReadBenchmarks.ZipArchiveRead"
|
||||
```
|
||||
|
||||
### Quick Dry Run (for testing)
|
||||
```bash
|
||||
dotnet run -c Release -- --job dry
|
||||
```
|
||||
|
||||
## Benchmark Categories
|
||||
|
||||
### ArchiveReadBenchmarks
|
||||
Tests the **Archive API** which provides random access to entries with seekable streams. Covers:
|
||||
- Zip (deflate compression)
|
||||
- Tar (uncompressed)
|
||||
- Tar.gz (gzip compression)
|
||||
- Tar.bz2 (bzip2 compression)
|
||||
- 7Zip (LZMA2 compression)
|
||||
- Rar
|
||||
|
||||
### ReaderBenchmarks
|
||||
Tests the **Reader API** which provides forward-only streaming for non-seekable streams. Covers:
|
||||
- Zip
|
||||
- Tar
|
||||
- Tar.gz
|
||||
- Tar.bz2
|
||||
- Rar
|
||||
|
||||
### WriteBenchmarks
|
||||
Tests the **Writer API** for creating archives using forward-only writing. Covers:
|
||||
- Zip (deflate compression)
|
||||
- Tar (uncompressed)
|
||||
- Tar.gz (gzip compression)
|
||||
|
||||
### BaselineComparisonBenchmarks
|
||||
Example benchmark showing how to compare implementations using the `[Baseline]` attribute. The baseline benchmark serves as a reference point, and BenchmarkDotNet calculates the ratio of performance between baseline and other methods.
|
||||
|
||||
## Comparing Against Previous Versions
|
||||
|
||||
### Using Baseline Attribute
|
||||
Mark one benchmark with `[Baseline = true]` and BenchmarkDotNet will show relative performance:
|
||||
|
||||
```csharp
|
||||
[Benchmark(Baseline = true)]
|
||||
public void MethodA() { /* ... */ }
|
||||
|
||||
[Benchmark]
|
||||
public void MethodB() { /* ... */ }
|
||||
```
|
||||
|
||||
Results will show ratios like "1.5x slower" or "0.8x faster" compared to the baseline.
|
||||
|
||||
### Using BenchmarkDotNet.Artifacts for Historical Comparison
|
||||
BenchmarkDotNet saves results to `BenchmarkDotNet.Artifacts/results/`. You can:
|
||||
|
||||
1. Run benchmarks and save the results
|
||||
2. Keep a snapshot of the results file
|
||||
3. Compare new runs against saved results
|
||||
|
||||
### Using Different NuGet Versions (Advanced)
|
||||
To compare against a published NuGet package:
|
||||
|
||||
1. Create a separate benchmark project referencing the NuGet package
|
||||
2. Use BenchmarkDotNet's `[SimpleJob]` attribute with different runtimes
|
||||
3. Reference both the local project and NuGet package in different jobs
|
||||
|
||||
## Interpreting Results
|
||||
|
||||
BenchmarkDotNet provides:
|
||||
- **Mean**: Average execution time
|
||||
- **Error**: Half of 99.9% confidence interval
|
||||
- **StdDev**: Standard deviation of measurements
|
||||
- **Allocated**: Memory allocated per operation
|
||||
- **Rank**: Relative ranking (when using `[RankColumn]`)
|
||||
- **Ratio**: Relative performance vs baseline (when using `[Baseline]`)
|
||||
|
||||
## Output Artifacts
|
||||
|
||||
Results are saved to `BenchmarkDotNet.Artifacts/results/`:
|
||||
- `*.csv`: Raw data for further analysis
|
||||
- `*-report.html`: HTML report with charts
|
||||
- `*-report-github.md`: Markdown report for GitHub
|
||||
- `*.log`: Detailed execution log
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always run in Release mode**: Debug builds have significant overhead
|
||||
2. **Close other applications**: Minimize system noise during benchmarks
|
||||
3. **Run multiple times**: Look for consistency across runs
|
||||
4. **Use appropriate workload**: Ensure benchmarks run for at least 100ms
|
||||
5. **Track trends**: Compare results over time to detect regressions
|
||||
6. **Archive results**: Keep snapshots of benchmark results for historical comparison
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
Consider adding benchmarks to CI/CD to:
|
||||
- Detect performance regressions automatically
|
||||
- Track performance trends over time
|
||||
- Compare PR performance against main branch
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [BenchmarkDotNet Documentation](https://benchmarkdotnet.org/articles/overview.html)
|
||||
- [BenchmarkDotNet Configuration](https://benchmarkdotnet.org/articles/configs/configs.html)
|
||||
- [BenchmarkDotNet Baseline](https://benchmarkdotnet.org/articles/features/baselines.html)
|
||||
88
tests/SharpCompress.Performance/ReaderBenchmarks.cs
Normal file
88
tests/SharpCompress.Performance/ReaderBenchmarks.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Benchmarks for Reader API operations across different formats.
|
||||
/// Reader API is used for forward-only streaming with non-seekable streams.
|
||||
/// </summary>
|
||||
[MemoryDiagnoser]
|
||||
public class ReaderBenchmarks : BenchmarkBase
|
||||
{
|
||||
[Benchmark]
|
||||
public void ZipReaderRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Zip.deflate.zip");
|
||||
using var stream = File.OpenRead(path);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarReaderRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar");
|
||||
using var stream = File.OpenRead(path);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarGzReaderRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar.gz");
|
||||
using var stream = File.OpenRead(path);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarBz2ReaderRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Tar.tar.bz2");
|
||||
using var stream = File.OpenRead(path);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void RarReaderRead()
|
||||
{
|
||||
var path = GetTestArchivePath("Rar.rar");
|
||||
using var stream = File.OpenRead(path);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" />
|
||||
<PackageReference Include="JetBrains.Profiler.SelfApi" />
|
||||
<ProjectReference Include="..\..\src\SharpCompress\SharpCompress.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
106
tests/SharpCompress.Performance/WriteBenchmarks.cs
Normal file
106
tests/SharpCompress.Performance/WriteBenchmarks.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writers;
|
||||
|
||||
namespace SharpCompress.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Benchmarks for Writer operations.
|
||||
/// Tests creating archives with different compression formats using forward-only Writer API.
|
||||
/// </summary>
|
||||
[MemoryDiagnoser]
|
||||
public class WriteBenchmarks : BenchmarkBase
|
||||
{
|
||||
private string _tempOutputPath = null!;
|
||||
private string[] _testFiles = null!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_tempOutputPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(_tempOutputPath);
|
||||
|
||||
// Get some test files to compress
|
||||
var originalPath = Path.Combine(Path.GetDirectoryName(TEST_ARCHIVES_PATH)!, "Original");
|
||||
if (Directory.Exists(originalPath))
|
||||
{
|
||||
_testFiles = Directory.GetFiles(originalPath).Take(5).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
_testFiles = [];
|
||||
}
|
||||
}
|
||||
|
||||
[IterationCleanup]
|
||||
public void IterationCleanup()
|
||||
{
|
||||
// Clean up created archives after each iteration to avoid file reuse affecting measurements
|
||||
if (Directory.Exists(_tempOutputPath))
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(_tempOutputPath))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
if (Directory.Exists(_tempOutputPath))
|
||||
{
|
||||
Directory.Delete(_tempOutputPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ZipWriterWrite()
|
||||
{
|
||||
var outputFile = Path.Combine(_tempOutputPath, "test.zip");
|
||||
using var stream = File.Create(outputFile);
|
||||
using var writer = WriterFactory.Open(
|
||||
stream,
|
||||
ArchiveType.Zip,
|
||||
new WriterOptions(CompressionType.Deflate)
|
||||
);
|
||||
foreach (var file in _testFiles)
|
||||
{
|
||||
writer.Write(Path.GetFileName(file), file);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarWriterWrite()
|
||||
{
|
||||
var outputFile = Path.Combine(_tempOutputPath, "test.tar");
|
||||
using var stream = File.Create(outputFile);
|
||||
using var writer = WriterFactory.Open(
|
||||
stream,
|
||||
ArchiveType.Tar,
|
||||
new WriterOptions(CompressionType.None)
|
||||
);
|
||||
foreach (var file in _testFiles)
|
||||
{
|
||||
writer.Write(Path.GetFileName(file), file);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TarGzWriterWrite()
|
||||
{
|
||||
var outputFile = Path.Combine(_tempOutputPath, "test.tar.gz");
|
||||
using var stream = File.Create(outputFile);
|
||||
using var writer = WriterFactory.Open(
|
||||
stream,
|
||||
ArchiveType.Tar,
|
||||
new WriterOptions(CompressionType.GZip)
|
||||
);
|
||||
foreach (var file in _testFiles)
|
||||
{
|
||||
writer.Write(Path.GetFileName(file), file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,24 @@
|
||||
"version": 2,
|
||||
"dependencies": {
|
||||
"net10.0": {
|
||||
"BenchmarkDotNet": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.14.0, )",
|
||||
"resolved": "0.14.0",
|
||||
"contentHash": "eIPSDKi3oni734M1rt/XJAwGQQOIf9gLjRRKKJ0HuVy3vYd7gnmAIX1bTjzI9ZbAY/nPddgqqgM/TeBYitMCIg==",
|
||||
"dependencies": {
|
||||
"BenchmarkDotNet.Annotations": "0.14.0",
|
||||
"CommandLineParser": "2.9.1",
|
||||
"Gee.External.Capstone": "2.3.0",
|
||||
"Iced": "1.17.0",
|
||||
"Microsoft.CodeAnalysis.CSharp": "4.1.0",
|
||||
"Microsoft.Diagnostics.Runtime": "2.2.332302",
|
||||
"Microsoft.Diagnostics.Tracing.TraceEvent": "3.1.8",
|
||||
"Microsoft.DotNet.PlatformAbstractions": "3.1.6",
|
||||
"Perfolizer": "[0.3.17]",
|
||||
"System.Management": "5.0.0"
|
||||
}
|
||||
},
|
||||
"JetBrains.Profiler.SelfApi": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.5.15, )",
|
||||
@@ -37,6 +55,26 @@
|
||||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"BenchmarkDotNet.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.14.0",
|
||||
"contentHash": "CUDCg6bgHrDzhjnA+IOBl5gAo8Y5hZ2YSs7MBXrYMlMKpBZqrD5ez0537uDveOkcf+YWAoK+S4sMcuWPbIz8bw=="
|
||||
},
|
||||
"CommandLineParser": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.9.1",
|
||||
"contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
|
||||
},
|
||||
"Gee.External.Capstone": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.3.0",
|
||||
"contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
|
||||
},
|
||||
"Iced": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.17.0",
|
||||
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
|
||||
},
|
||||
"JetBrains.FormatRipper": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.4.0",
|
||||
@@ -63,6 +101,118 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
|
||||
},
|
||||
"Microsoft.CodeAnalysis.Analyzers": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.3.3",
|
||||
"contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ=="
|
||||
},
|
||||
"Microsoft.CodeAnalysis.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "bNzTyxP3iD5FPFHfVDl15Y6/wSoI7e3MeV0lOaj9igbIKTjgrmuw6LoVJ06jUNFA7+KaDC/OIsStWl/FQJz6sQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.CodeAnalysis.Analyzers": "3.3.3"
|
||||
}
|
||||
},
|
||||
"Microsoft.CodeAnalysis.CSharp": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.1.0",
|
||||
"contentHash": "sbu6kDGzo9bfQxuqWpeEE7I9P30bSuZEnpDz9/qz20OU6pm79Z63+/BsAzO2e/R/Q97kBrpj647wokZnEVr97w==",
|
||||
"dependencies": {
|
||||
"Microsoft.CodeAnalysis.Common": "[4.1.0]"
|
||||
}
|
||||
},
|
||||
"Microsoft.Diagnostics.NETCore.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.2.251802",
|
||||
"contentHash": "bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.AsyncInterfaces": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Diagnostics.Runtime": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.332302",
|
||||
"contentHash": "Hp84ivxSKIMTBzYSATxmUsm3YSXHWivcwiRRbsydGmqujMUK8BAueLN0ssAVEOkOBmh0vjUBhrq7YcroT7VCug==",
|
||||
"dependencies": {
|
||||
"Microsoft.Diagnostics.NETCore.Client": "0.2.251802"
|
||||
}
|
||||
},
|
||||
"Microsoft.Diagnostics.Tracing.TraceEvent": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.8",
|
||||
"contentHash": "kl3UMrZKSeSEYZ8rt/GjLUQToREjgQABqfg6PzQBmSlYHTZOKE9ePEOS2xptROQ9SVvngg3QGX51TIT11iZ0wA=="
|
||||
},
|
||||
"Microsoft.DotNet.PlatformAbstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.1.6",
|
||||
"contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg=="
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA=="
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Binder": "2.1.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "2.1.1",
|
||||
"Microsoft.Extensions.Options": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1",
|
||||
"Microsoft.Extensions.Primitives": "2.1.1"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.1",
|
||||
"contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg=="
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies.net461": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.0.3",
|
||||
@@ -73,8 +223,33 @@
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
|
||||
},
|
||||
"Perfolizer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.3.17",
|
||||
"contentHash": "FQgtCoF2HFwvzKWulAwBS5BGLlh8pgbrJtOp47jyBwh2CW16juVtacN1azOA2BqdrJXkXTNLNRMo7ZlHHiuAnA=="
|
||||
},
|
||||
"System.CodeDom": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "JPJArwA1kdj8qDAkY2XGjSWoYnqiM7q/3yRNkt6n28Mnn95MuEGkZXUbPBf7qc3IjwrGY5ttQon7yqHZyQJmOQ=="
|
||||
},
|
||||
"System.Management": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "MF1CHaRcC+MLFdnDthv4/bKWBZnlnSpkGqa87pKukQefgEdwtb9zFW6zs0GjPp73qtpYYg4q6PEKbzJbxCpKfw==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "5.0.0",
|
||||
"System.CodeDom": "5.0.0"
|
||||
}
|
||||
},
|
||||
"sharpcompress": {
|
||||
"type": "Project"
|
||||
},
|
||||
"Microsoft.Bcl.AsyncInterfaces": {
|
||||
"type": "CentralTransitive",
|
||||
"requested": "[10.0.0, )",
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user