Skip to content

File.*AllText* optimizations - #58167

Merged
adamsitnik merged 18 commits into
dotnet:mainfrom
adamsitnik:fileOptimizations
Oct 14, 2021
Merged

File.*AllText* optimizations#58167
adamsitnik merged 18 commits into
dotnet:mainfrom
adamsitnik:fileOptimizations

Conversation

@adamsitnik

@adamsitnikadamsitnik commented Aug 26, 2021

Copy link
Copy Markdown
Member

The reduced memory allocations come from lack of StreamWriter and FileStream buffer allocations.

The reduced CPU time comes mostly from using bigger buffers and setting file preallocation size.

Windows

Details
MethodJobsizeRatioAllocated
AppendAllTextafter1001.00120 B
AppendAllTextbefore1001.006,576 B
WriteAllTextafter1001.00120 B
WriteAllTextbefore1001.006,576 B
AppendAllTextAsyncafter1001.00697 B
AppendAllTextAsyncbefore1001.0010,586 B
WriteAllTextAsyncafter1001.00761 B
WriteAllTextAsyncbefore1001.0010,649 B
AppendAllTextafter100000.87121 B
AppendAllTextbefore100001.009,680 B
WriteAllTextafter100000.80125 B
WriteAllTextbefore100001.009,683 B
AppendAllTextAsyncafter100000.85698 B
AppendAllTextAsyncbefore100001.0011,049 B
WriteAllTextAsyncafter100000.43768 B
WriteAllTextAsyncbefore100001.0011,256 B
WriteAllTextafter300000.75125 B
WriteAllTextbefore300001.009,683 B
WriteAllTextAsyncafter300000.54765 B
WriteAllTextAsyncbefore300001.0011,997 B
WriteAllTextafter700000.79126 B
WriteAllTextbefore700001.009,683 B
WriteAllTextAsyncafter700000.49767 B
WriteAllTextAsyncbefore700001.0013,387 B
WriteAllTextafter1000000.77124 B
WriteAllTextbefore1000001.009,683 B
WriteAllTextAsyncafter1000000.58770 B
WriteAllTextAsyncbefore1000001.0014,630 B

Ubuntu

Details
MethodToolchainsizeRatioAllocated
AppendAllText/after/corerun1000.73112 B
AppendAllText/before/corerun1001.006,568 B
WriteAllText/after/corerun1000.94112 B
WriteAllText/before/corerun1001.006,568 B
AppendAllTextAsync/after/corerun1000.60480 B
AppendAllTextAsync/before/corerun1001.0010,368 B
WriteAllTextAsync/after/corerun1000.81544 B
WriteAllTextAsync/before/corerun1001.0010,427 B
AppendAllText/after/corerun100000.72112 B
AppendAllText/before/corerun100001.009,672 B
WriteAllText/after/corerun100000.69112 B
WriteAllText/before/corerun100001.009,672 B
AppendAllTextAsync/after/corerun100000.63480 B
AppendAllTextAsync/before/corerun100001.0010,890 B
WriteAllTextAsync/after/corerun100000.44497 B
WriteAllTextAsync/before/corerun100001.0011,072 B
WriteAllText/after/corerun1000000.56112 B
WriteAllText/before/corerun1000001.009,673 B
WriteAllTextAsync/after/corerun1000000.43545 B
WriteAllTextAsync/before/corerun1000001.0014,413 B

@adamsitnikadamsitnik added area-System.IO tenet-performance Performance related issue labels Aug 26, 2021
@adamsitnikadamsitnik added this to the 7.0.0 milestone Aug 26, 2021
@adamsitnik
adamsitnik requested a review from jozkeeAugust 26, 2021 10:29
@ghost

Copy link
Copy Markdown

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

Issue Details

The reduced memory allocations come from lack of StreamWriter and FileStream buffer allocations.

The reduced CPU time comes mostly from using bigger buffers and setting file preallocation size.

MethodJobsizeRatioAllocated
AppendAllTextafter1001.00121 B
AppendAllTextbefore1001.006,576 B
WriteAllTextafter1001.01121 B
WriteAllTextbefore1001.006,577 B
AppendAllTextAsyncafter1001.00713 B
AppendAllTextAsyncbefore1001.0010,585 B
WriteAllTextAsyncafter1000.98778 B
WriteAllTextAsyncbefore1001.0010,648 B
AppendAllTextafter100000.91121 B
AppendAllTextbefore100001.009,680 B
WriteAllTextafter100000.85123 B
WriteAllTextbefore100001.009,682 B
AppendAllTextAsyncafter100000.84714 B
AppendAllTextAsyncbefore100001.0011,048 B
WriteAllTextAsyncafter100000.89789 B
WriteAllTextAsyncbefore100001.0011,242 B
WriteAllTextafter1000000.85126 B
WriteAllTextbefore1000001.009,684 B
WriteAllTextAsyncafter1000000.72785 B
WriteAllTextAsyncbefore1000001.0014,598 B
Author:adamsitnik
Assignees:-
Labels:

area-System.IO, tenet-performance

Milestone:7.0.0

@adamsitnikadamsitnik changed the title File optimizationsFile.*AllText* optimizationsAug 26, 2021
@adamsitnik

Copy link
Copy Markdown
MemberAuthor

@jozkee please let me know if you would like me to separate the refactor from the optimizations

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
{
if (path == null)
throw new ArgumentNullException(nameof(path));
Validate(path, encoding);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's probably fine, but this does change which exception will be thrown if there are multiple things wrong.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
@danmoseley

Copy link
Copy Markdown
Contributor

I assume no new tests are warranted as it's purely perf, but having touched this code can you see any we maybe are missing?

@adamsitnik

Copy link
Copy Markdown
MemberAuthor

@stephentoub@danmoseley I've added missing tests, which identified a bug, fixed it and updated perf numbers to include Linux numbers as well. On Linux it's now even two times faster for large strings!

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs Outdated

@jozkeejozkee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Otherwise; LGTM, Thanks.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/File.cs Outdated
Comment threadsrc/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs Outdated
Comment threadsrc/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs Outdated
@adamsitnik

Copy link
Copy Markdown
MemberAuthor

I am closing the PR as it's pointless with the regression that has been recently introduced and backported to 6.0 (#59705)

@stephentoub

Copy link
Copy Markdown
Member

@stephentoub

Copy link
Copy Markdown
Member

You'd made a bunch of style changes, consolidating input validation, etc. Do you want to keep those?

@adamsitnik

adamsitnik commented Oct 12, 2021

Copy link
Copy Markdown
MemberAuthor

Conversely, it was also buggy after

It was, because I wanted to clarify how preallocationSize should work, make sure that everyone agrees and then update this PR.

@adamsitnikadamsitnik reopened this Oct 14, 2021
@adamsitnik

Copy link
Copy Markdown
MemberAuthor

I was able to get some nice perf wins anyway (mostly due to using larger buffers which reduced the number of sys-calls). The failures are not related (System.IO.Tests.FileStream_DeleteOnClose.OpenOrCreate_DeleteOnClose_UsableAsMutex), I am merging it.

@adamsitnik
adamsitnik merged commit cf49643 into dotnet:mainOct 14, 2021
@adamsitnik
adamsitnik deleted the fileOptimizations branch October 14, 2021 14:40
@danmoseley

Copy link
Copy Markdown
Contributor

Nice!

@kunalspathak

Copy link
Copy Markdown
Contributor

Ubuntu x64 improvements - dotnet/perf-autofiling-issues#1897

@kunalspathak

Copy link
Copy Markdown
Contributor

alpine improvements - dotnet/perf-autofiling-issues#1922

@kunalspathak

Copy link
Copy Markdown
Contributor

windows x64 improvements - dotnet/perf-autofiling-issues#1933

@danmoseley

Copy link
Copy Markdown
Contributor

woo hoo.

also, @kunalspathak@adamsitnik what happened here? it's not obvious to me that this change improved File.Exists --

image

@kunalspathak

Copy link
Copy Markdown
Contributor

@danmoseley

Copy link
Copy Markdown
Contributor

A curious bimodality that seems to stay in one state for a week or more. I wonder whether iterations within an individual run are stable? I don't see a way to determine from the report.

@ghostghost locked as resolved and limited conversation to collaborators Nov 18, 2021
@AndyAyersMS

Copy link
Copy Markdown
Member

Improvement dotnet/perf-autofiling-issues#1795 (click on full history to see)
newplot (85)

@adamsitnik

adamsitnik commented Nov 23, 2021

Copy link
Copy Markdown
MemberAuthor

It's interesting that it got both faster and more stable despite still being an IO benchmark. I suspect that it might be caused by using the preallocation size which avoids fragmentation.

@danmoseley

Copy link
Copy Markdown
Contributor

That is a beautiful graph. Nice.

@jeffhandley

Copy link
Copy Markdown
Member

That is a beautiful graph. Nice.

Wow; it really is! Great work, and I love seeing the data loop closed like this, attributing the improvements to the change.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.IOtenet-performancePerformance related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@adamsitnik@danmoseley@jeffhandley@stephentoub@kunalspathak@AndyAyersMS@campersau@JeremyKuhne@jozkee