Skip to content

Add ZipArchive metadata read benchmarks - #5303

Open
agocke wants to merge 1 commit into
dotnet:mainfrom
agocke:runtime-async-ziparchive
Open

agocke wants to merge 1 commit into
dotnet:mainfrom
agocke:runtime-async-ziparchive

Conversation

@agocke

@agocke agocke commented Sep 7, 2026

Copy link
Copy Markdown
Member

Summary

  • Add realistic ZipArchive metadata-reading benchmarks using a generated ZIP containing JSON package metadata and payload entries.
  • Cover synchronous and asynchronous reads from both memory and file streams.
  • Move the runtime-async feature gate to the repository root so BenchmarkDotNet-generated projects under artifacts/ inherit it.

The public async benchmark uses a synchronous BenchmarkDotNet entrypoint around a private async workload. This avoids BenchmarkDotNet generating an async void runner state machine while preserving runtime-async compilation for the measured workload.

Runtime comparison

Using matched compiler-async and runtime-async benchmark builds and System.IO.Compression CoreRoots:

Source Compiler async Runtime async Time Allocation
Memory 19.61 us, 29,568 B 18.56 us, 26,560 B 5.3% faster 10.2% less
File 424.71 us, 36,030 B 375.88 us, 33,044 B 11.5% faster 8.3% less

The results reproduced across two paired runs. The runtime-async benchmark workload contains no generated async state machine.

Add sync and async ZipArchive metadata-reading benchmarks over memory and file streams. Move the runtime-async feature gate to the repository root so BenchmarkDotNet-generated projects inherit it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6957835-b7f3-45ee-875f-4efad68e3c4e
Copilot AI lite review requested due to automatic review settings September 7, 2026 19:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The changes look correct and aligned with the stated benchmarking/build goals, with only a minor benchmark-noise improvement suggested.

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity src/​benchmarks/​micro/​libraries/​System.IO.Compression/​ZipArchive.cs — GetMetadataEntry uses LINQ (Entries.First + predicate), which adds extra overhead/allocations into…
What changed in this PR

This pull request adds new microbenchmarks to measure ZipArchive metadata-reading performance across sync/async and memory/file-backed streams, and adjusts the build so the runtime-async feature gate is applied from the repository root (allowing BenchmarkDotNet-generated projects under artifacts/ to inherit it).

Changes:

  • Added a ZipArchive metadata-reading benchmark that generates a representative ZIP (JSON metadata + payload entries) and measures sync vs async read paths from memory and file streams.
  • Moved the runtime-async feature gating logic from src/Directory.Build.targets into the repository root Directory.Build.targets.
  • Removed the now-unneeded src/Directory.Build.targets.
File Description
src/​Directory.Build.targets Removed subdirectory build targets so the root targets apply directly under src/.
src/​benchmarks/​micro/​libraries/​System.IO.Compression/​ZipArchive.cs New microbenchmark for reading ZIP entry metadata (sync/async, memory/file).
Directory.Build.targets Added root-level runtime-async feature gating so generated BDN projects under artifacts/ inherit it.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +120 to +121
private static ZipArchiveEntry GetMetadataEntry(ZipArchive archive) =>
archive.Entries.First(entry => entry.FullName == "package-metadata.json");
@timcassell

timcassell commented Sep 7, 2026

Copy link
Copy Markdown

This avoids BenchmarkDotNet generating an async void runner state machine while preserving runtime-async compilation for the measured workload.

What's the issue with async void calling async Task<int>? As far as I'm aware, the generated project should pick up the runtime-async feature from the root targets. And that generated code should result in better measurements than the GetAwaiter().GetResult() method.

The public async benchmark uses a synchronous BenchmarkDotNet entrypoint around a private async workload.

You can also use [ConsumeTasksSynchronously(true)] instead of manually wrapping it if you need that behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants