Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change ZipBlocks structs to classes #113453

Merged
merged 11 commits into from
Mar 21, 2025

Conversation

carlossanlop
Copy link
Member

@carlossanlop carlossanlop commented Mar 12, 2025

Contributes to #1541

Structs cannot be passed around in async code (a copy gets created), we need to convert them to classes so they can be used in the incoming async code.

Here's the perf impact comparison before and after:

Method Toolchain Mean Error StdDev Median Min Max Ratio RatioSD Allocated Alloc Ratio
ZipFileCreateFromDirectory Before
(struct)
11.16 ms 0.485 ms 0.558 ms 11.13 ms 10.05 ms 12.16 ms 1.00 0.07 10.12 KB 1.00
ZipFileCreateFromDirectory After
(class)
11.59 ms 0.535 ms 0.572 ms 11.41 ms 11.00 ms 13.05 ms 1.04 0.07 10.3 KB 1.02

I used the benchmarks that I am proposing in this PR dotnet/performance#4764

cc @edwardneal you might be interested in this change.

@carlossanlop carlossanlop self-assigned this Mar 12, 2025
@Copilot Copilot bot review requested due to automatic review settings March 12, 2025 23:24
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-io-compression
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR converts several ZipBlock types from structs to classes to prevent unintended copying in async scenarios. The key changes include:

  • Converting multiple structs (e.g. ZipGenericExtraField, Zip64ExtraField, etc.) into sealed classes.
  • Changing default initializations from “default” to “new()” with object initializers.
  • Adjusting nullability of fields to support class semantics.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs Converted various Zip* types from structs to sealed classes, updating initialization and field nullability.
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.FieldLengths.cs Updated type declarations from struct to sealed class for consistency.
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.FieldLocations.cs Converted type declarations from struct to sealed class for consistency.
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs Updated default instantiation of Zip64ExtraField references to use “new()”.
src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchive.cs Updated instantiation of ZipCentralDirectoryFileHeader from struct to class.
Comments suppressed due to low confidence (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs:780

  • The lazy initialization in the ArchiveComment getter guarantees a non-null return but may hide cases where the archive comment was expected to be explicitly set. Please confirm that this behavior is intended and that it does not mask potential errors in data handling.
public byte[] ArchiveComment { get { _archiveComment ??= []; return _archiveComment; } }

@carlossanlop carlossanlop mentioned this pull request Mar 12, 2025
15 tasks
@stephentoub
Copy link
Member

Can you point to an example for why these need to change to support async?

@carlossanlop
Copy link
Member Author

Can you point to an example for why these need to change to support async?

Of course. We had the exact same problem with Tar: #72472

Copy link
Member

@michaelgsharp michaelgsharp left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@edwardneal edwardneal left a comment

Choose a reason for hiding this comment

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

Thanks for the mention @carlossanlop. Some of these classes are fairly large and I think we could save allocating a few instances, but I could easily follow up with those separately if we want to keep this PR clear.

Copy link
Contributor

@IDisposable IDisposable left a comment

Choose a reason for hiding this comment

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

Looks pretty good

@carlossanlop
Copy link
Member Author

/ba-g failures are timeouts: The job running on agent NetCore-Public 419 ran longer than the maximum time of 240 minutes.

@carlossanlop carlossanlop merged commit 44c08b8 into dotnet:main Mar 21, 2025
77 of 84 checks passed
@carlossanlop carlossanlop deleted the ZipStructToClass branch March 21, 2025 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants