Skip to content

Conversation

@alinpahontu2912
Copy link
Member

@alinpahontu2912 alinpahontu2912 commented Sep 8, 2025

Improve byte array allocations for comments reading

Fixes #64767

Copy link
Contributor

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 improves memory allocation performance in the ZipHelper.GetEncodedTruncatedBytesFromString method by replacing direct byte array allocation with ArrayPool<byte> for temporary storage, reducing garbage collection pressure.

Key Changes

  • Replaces encoding.GetBytes(text) allocation with pooled array rental
  • Adds proper array pooling with try/finally pattern for resource cleanup
  • Maintains existing functionality while reducing memory allocations

@alinpahontu2912
Copy link
Member Author

alinpahontu2912 commented Oct 2, 2025

Hello @jkotas @stephentoub, I ran some benchmarks to compare the initial method, then the arraypool approach and then using jan's suggestion and I think based on the results, Jan's version offers the best improvements. benchmarks.ods

@MartyIX
Copy link
Contributor

MartyIX commented Oct 2, 2025

Hello @jkotas @stephentoub, I ran some benchmarks to compare the initial method, then the arraypool approach and then using jan's suggestion and I think based on the results, Jan's version offers the best improvements. benchmarks.ods

Could you post it as text or as a screenshot? Not everyone have installed Libre Office.

@GerardSmit
Copy link
Contributor

Content of benchmarks.ods:

Input: string('A', 5000);

Method MaxBytes Mean StdDev Allocated Ratio
InitialImplementation 32 444 ns 5.83 ns 5,080 B 1
JanSuggestion 32 364 ns 7.96 ns 5,080 B 0.82
ArrayPoolImplementation 32 145 ns 1.34 ns 56 B 0.33
InitialImplementation 256 879 ns 20.80 ns 5,304 B 1
JanSuggestion 256 381 ns 7.00 ns 5,304 B 0.43
ArrayPoolImplementation 256 566 ns 5.47 ns 280 B 0.64
InitialImplementation 4096 8,007 ns 135 ns 9,144 B 1
JanSuggestion 4096 495 ns 8.42 ns 9,144 B 0.06
ArrayPoolImplementation 4096 7,760 ns 139 ns 4,120 B 0.97
InitialImplementation 65535 362 ns 19.6 ns 5,024 B 1
JanSuggestion 65535 364 ns 7.93 ns 5,024 B 1.01
ArrayPoolImplementation 65535 360 ns 15.87 ns 5,024 B 1

Input: string.Concat(Enumerable.Repeat("😀😎🚀🔥", 1000));

Method MaxBytes Mean StdDev Allocated Ratio
InitialImplementation 32 9,780 ns 3,351 ns 16,080 B 1.1
JanSuggestion 32 7,000 ns 122 ns 16,080 B 0.79
ArrayPoolImplementation 32 163 ns 2.14 ns 56 B 0.02
InitialImplementation 256 7,056 ns 68 ns 16,304 B 1
JanSuggestion 256 7,155 ns 51 ns 16,304 B 1.01
ArrayPoolImplementation 256 420 ns 3.48 ns 280 B 0.06
InitialImplementation 4096 9,736 ns 80 ns 20,144 B 1
JanSuggestion 4096 6,973 ns 57 ns 20,144 B 0.72
ArrayPoolImplementation 4096 4,493 ns 29 ns 4,120 B 0.46
InitialImplementation 65535 7,021 ns 196 ns 16,024 B 1
JanSuggestion 65535 6,828 ns 64 ns 16,024 B 0.97
ArrayPoolImplementation 65535 7,165 ns 123 ns 16,024 B 1.02

Input:string('X', 50_000);

Method MaxBytes Mean StdDev Allocated Ratio
InitialImplementation 32 4.185 us 0.062 us 50,080 B 1
JanSuggestion 32 4.080 us 0.092 us 50,080 B 0.98
ArrayPoolImplementation 32 3.496 us 0.071 us 56 B 0.84
InitialImplementation 256 4.766 us 0.046 us 50,304 B 1
JanSuggestion 256 4.153 us 0.091 us 50,304 B 0.87
ArrayPoolImplementation 256 4.329 us 0.024 us 280 B 0.91
InitialImplementation 4096 11.953 us 0.137 us 54,144 B 1
JanSuggestion 4096 4.203 us 0.049 us 54,144 B 0.35
ArrayPoolImplementation 4096 11.281 us 0.160 us 4120 B 0.94
InitialImplementation 65535 99.367 us 0.825 us 100048 B 1
JanSuggestion 65535 3.961 us 0.048 us 50024 B 0.04
ArrayPoolImplementation 65535 101.390 us 2.126 us 50024 B 1.02

Input: string.Concat(Enumerable.Repeat("X😀XX", 10_000));

Method MaxBytes Mean StdDev Allocated Ratio
InitialImplementation 32 73.671 us 16.954 us 70,080 B 1
JanSuggestion 32 51.803 us 1.494 us 70,080 B 0.75
ArrayPoolImplementation 32 3.983 us 0.073 us 56 B 0.06
InitialImplementation 256 51.403 us 0.926 us 70,304 B 1
JanSuggestion 256 50.840 us 0.777 us 70,304 B 0.99
ArrayPoolImplementation 256 4.392 us 0.068 us 280 B 0.09
InitialImplementation 4096 55.915 us 0.655 us 74,144 B 1
JanSuggestion 4096 51.512 us 1.111 us 74,144 B 0.92
ArrayPoolImplementation 4096 11.704 us 0.283 us 4,120 B 0.21
InitialImplementation 65535 123.779 us 4.680 us 135,584 B 1
JanSuggestion 65535 43.978 us 0.750 us 135,584 B 0.36
ArrayPoolImplementation 65535 109.527 us 2.464 us 65,560 B 0.89

@alinpahontu2912 alinpahontu2912 changed the title Use ArrayPool to improve performance Improve performance of decoding zip comments Oct 14, 2025
@alinpahontu2912
Copy link
Member Author

Hey @jkotas @stephentoub, what do you think about these changes?

@alinpahontu2912 alinpahontu2912 changed the title Improve performance of decoding zip comments Improve performance of reading zip comments Oct 14, 2025
@stephentoub stephentoub merged commit 61f9df8 into dotnet:main Oct 15, 2025
85 checks passed
@alinpahontu2912 alinpahontu2912 deleted the update_byte_array_allocation branch October 20, 2025 08:07
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.

Improve how byte arrays are created in ZipHelper.GetEncodedTruncatedBytesFromString

5 participants