-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Improve performance of Tar library #74281
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
Changes from 1 commit
d52d836
1e5020e
6938c77
5fa03e9
8dd0ac1
5be57ad
ab71e6c
df2d742
c6058bd
5756a8c
9539a4a
74bbc9c
46e0855
02ca7da
f9eb99f
add6179
6f8cb75
827a588
ae21478
d6b6727
480af5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -531,8 +531,8 @@ private static async Task WriteDataAsync(Stream archiveStream, Stream dataStream | |
| if (paddingAfterData != 0) | ||
| { | ||
| byte[] buffer = ArrayPool<byte>.Shared.Rent(paddingAfterData); | ||
|
|
||
| Array.Clear(buffer, 0, paddingAfterData); | ||
|
|
||
| await archiveStream.WriteAsync(buffer.AsMemory(0, paddingAfterData), cancellationToken).ConfigureAwait(false); | ||
|
|
||
| ArrayPool<byte>.Shared.Return(buffer); | ||
|
|
@@ -542,9 +542,11 @@ private static async Task WriteDataAsync(Stream archiveStream, Stream dataStream | |
| // Dumps into the archive stream an extended attribute entry containing metadata of the entry it precedes. | ||
| private static Stream? GenerateExtendedAttributesDataStream(Dictionary<string, string> extendedAttributes) | ||
| { | ||
| byte[]? buffer = null; | ||
| MemoryStream? dataStream = null; | ||
|
|
||
| byte[]? buffer = null; | ||
| Span<byte> span = stackalloc byte[512]; | ||
|
|
||
| if (extendedAttributes.Count > 0) | ||
| { | ||
| dataStream = new MemoryStream(); | ||
|
|
@@ -561,26 +563,27 @@ private static async Task WriteDataAsync(Stream archiveStream, Stream dataStream | |
| length += CountDigits(length); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was meant to model the logic previously there, but I think this logic needs to be tweaked, and it should be more like: int digitCount = CountDigits(length) ;
length += digitCount;
length += CountDigits(length) - digitCount; // account for possible digit length increaseDo we have tests for this stuff? Do we validate that the archives at produce are readable by other tools? Our own code appears to ignore this length when reading archives (maybe it shouldn't?)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we even sure the length is supposed to include itself? Have you seen that being done in archives produced by other tools? That would be a very strange format design.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From man tar 5:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree it's strange design. I did verify that the Since we know the length of the data section, I didn't feel it was too important to verify that the length of each extended attribute entry was correct, considering that we need to look for a mandatory newline char suffix. Maybe if we checked the length number and advanced the position instead of searching for the newline, we could improve perf a bit. I can investigate if this is true and determine if we need to submit a PR to verify the length number. |
||
|
|
||
| // Get a large enough buffer if we don't already have one. | ||
| if (buffer is null || buffer.Length < length) | ||
| if (span.Length < length) | ||
| { | ||
| if (buffer is not null) | ||
danmoseley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| ArrayPool<byte>.Shared.Return(buffer); | ||
| } | ||
| buffer = ArrayPool<byte>.Shared.Rent(length); | ||
| span = buffer; | ||
| } | ||
|
|
||
| // Format the contents. | ||
| bool formatted = Utf8Formatter.TryFormat(length, buffer, out int bytesWritten); | ||
| bool formatted = Utf8Formatter.TryFormat(length, span, out int bytesWritten); | ||
| Debug.Assert(formatted); | ||
| buffer[bytesWritten++] = (byte)' '; | ||
| bytesWritten += Encoding.UTF8.GetBytes(attribute, buffer.AsSpan(bytesWritten)); | ||
| buffer[bytesWritten++] = (byte)'='; | ||
| bytesWritten += Encoding.UTF8.GetBytes(value, buffer.AsSpan(bytesWritten)); | ||
| buffer[bytesWritten++] = (byte)'\n'; | ||
| span[bytesWritten++] = (byte)' '; | ||
| bytesWritten += Encoding.UTF8.GetBytes(attribute, span.Slice(bytesWritten)); | ||
| span[bytesWritten++] = (byte)'='; | ||
| bytesWritten += Encoding.UTF8.GetBytes(value, span.Slice(bytesWritten)); | ||
| span[bytesWritten++] = (byte)'\n'; | ||
|
|
||
| // Write it to the stream. | ||
| dataStream.Write(buffer.AsSpan(0, bytesWritten)); | ||
| dataStream.Write(span.Slice(0, bytesWritten)); | ||
| } | ||
|
|
||
| dataStream.Position = 0; // Ensure it gets written into the archive from the beginning | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.