Skip to content

Use ValueStringBuilder to fix allocations in ToString() methods of XdsDateTime and XsdDuration - #64868

Merged
stephentoub merged 7 commits into
dotnet:mainfrom
TrayanZapryanov:issue-64853
Feb 24, 2022
Merged

Use ValueStringBuilder to fix allocations in ToString() methods of XdsDateTime and XsdDuration#64868
stephentoub merged 7 commits into
dotnet:mainfrom
TrayanZapryanov:issue-64853

Conversation

@TrayanZapryanov

@TrayanZapryanovTrayanZapryanov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

FixesIssue: 64853

Benchmark results :
Before

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString79.56 ns1.238 ns0.967 ns79.64 ns77.60 ns81.20 ns0.0486408 B
DateTime_ToString_Local243.25 ns1.684 ns1.576 ns243.55 ns241.02 ns245.91 ns0.0541456 B
DateTime_ToString_Unspecified76.37 ns0.422 ns0.394 ns76.41 ns75.65 ns77.01 ns0.0487408 B
DateTime_ToString_RoundtripKind78.79 ns0.868 ns0.769 ns78.70 ns77.46 ns80.15 ns0.0485408 B
TimeSpan_ToString62.96 ns0.485 ns0.454 ns62.88 ns62.09 ns63.75 ns0.0200168 B

Using SpanFormattable:

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString129.07 ns1.138 ns1.009 ns129.34 ns125.84 ns129.72 ns0.0131112 B
DateTime_ToString_Local291.06 ns4.934 ns4.615 ns288.28 ns287.16 ns300.48 ns0.0139120 B
DateTime_ToString_Unspecified127.20 ns1.123 ns1.051 ns127.49 ns123.74 ns127.97 ns0.0134112 B
DateTime_ToString_RoundtripKind123.78 ns0.787 ns0.736 ns123.85 ns121.52 ns124.67 ns0.0132112 B
TimeSpan_ToString40.70 ns0.105 ns0.098 ns40.67 ns40.53 ns40.88 ns0.006656 B

Latest:

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString54.50 ns0.304 ns0.270 ns54.55 ns53.98 ns54.99 ns0.009680 B
DateTime_ToString_Local187.15 ns2.430 ns2.029 ns187.60 ns180.93 ns189.17 ns0.009988 B
DateTime_ToString_Unspecified49.17 ns0.523 ns0.464 ns49.24 ns47.62 ns49.50 ns0.009580 B
DateTime_ToString_RoundtripKind53.01 ns0.768 ns0.718 ns53.34 ns51.73 ns53.67 ns0.009580 B
TimeSpan_ToString41.16 ns0.206 ns0.192 ns41.22 ns40.55 ns41.31 ns0.006556 B

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Xml labels Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

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

Issue Details

Fixes Issue: 64853

Author:TrayanZapryanov
Assignees:-
Labels:

area-System.Xml, community-contribution

Milestone:-

@danmoseley

Copy link
Copy Markdown
Contributor

Could you please check that the unit tests cover these paths?

@danmoseley

Copy link
Copy Markdown
Contributor

Could you change the title to something descriptive? It is more useful than a number.

@TrayanZapryanovTrayanZapryanov changed the title Fixing Issue 64853Use ValueStringBuilder to fix allocations in ToString() methods of XdsDateTime and XsdDurationFeb 6, 2022
@TrayanZapryanov

Copy link
Copy Markdown
ContributorAuthor

Could you please check that the unit tests cover these paths?

Looks like existing tests already found a problem :)

Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs Outdated
Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs Outdated
Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs Outdated
Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs Outdated
@danmoseley

Copy link
Copy Markdown
Contributor

Would you mind evaluating whether there are unit tests for the areas you're changing? This code is old, and the tests are old too so there is some possibility that it is not properly tested as a regression might slip though.

@TrayanZapryanov

Copy link
Copy Markdown
ContributorAuthor

Would you mind evaluating whether there are unit tests for the areas you're changing? This code is old, and the tests are old too so there is some possibility that it is not properly tested as a regression might slip though.

Once I've applied feedback changes found that there are 3850 tests in XmlConvertTests.cs . The only thing that was not able to find is if DateTimeTypeCode.GYearMonth/GYear/GMonthDay/GDay/GMonth in XsdDateTime are tested. Maybe here somebody from owners can check.

}
}
}
}

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.

Thanks, but I didn't mean to separate it out into its own file. I meant just move the function to the primary ValueStringBuilder.cs file.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've tried, but it was not so easy as some things stopped building.
Can we do this in another PR ?

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.

Can we do this in another PR ?

I'd prefer we fix the problem in this PR, which would otherwise be duplicating the code for that function. What stopped building?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

C:\Work\Github\TZ_runtime\src\libraries\Common\src\System\Text\ValueStringBuilder.cs(276,110): error CS0246: The type or namespace name 'ISpanFormattable' could not be found (are you missing a using directive or an assembly reference?) [C:\Work\Github\TZ_runtime\src\libraries\System.Text.RegularExpressions\gen\System.Text.RegularExpressions.Generator.csproj] System.Text.Json.SourceGeneration.Roslyn3.11 -> C:\Work\Github\TZ_runtime\artifacts\bin\System.Text.Json.SourceGeneration.Roslyn3.11\Debug\netstandard2.0\System.Text.Json.SourceGeneration.dll

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.

Thanks. You should be able to fix that by adding this:

internalinterfaceISpanFormattable:IFormattable{boolTryFormat(Span<char>destination,outintcharsWritten,ReadOnlySpan<char>format,IFormatProvider?provider);}

here:

namespaceSystem
{
internalstaticclassStringExtensions

or something along those lines.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Something strange happens. When I build Release it is successful.
Command that I am executing is according build guide: build.cmd clr+libs -rc Release
But if I tri to build tests and to run them with : build.cmd -subset libs.tests -test -rc Release
Then I see errors, also if I open solutions in VS.
Next exception is:
1>C:\Work\Github\TZ_runtime\src\libraries\Common\src\System\Text\ValueStringBuilder.cs(276,110,276,126): error CS0246: The type or namespace name 'ISpanFormattable' could not be found (are you missing a using directive or an assembly reference?)
1>Done building project "System.Text.Encodings.Web.csproj" -- FAILED.

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.

Ok, if we have src projects using ValueStringBuilder.cs and building for downlevel, which that description suggests we are, this isn't going to be trivial. Sorry for sending you down a bad path. Let's back up. Instead of moving AppendSpanFormattable into the main file, let's do something similar to what you were at one point doing: put it in its own file... but not just in System.Private.Xml... put that file next to where the main one lives in common, and then just include the file into the projects that need AppendSpanFormattable... I think that'll just be System.Private.Corelib and System.Private.Xml. Hopefully that goes better. If you still run into troubles, push up your changes to this PR and I can pull it down and fix things up.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You can check if this is what you have in mind.
Also other comments resolved - just the name of new file is not so good, but it is descriptive :)

@TrayanZapryanovTrayanZapryanovFeb 7, 2022

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@stephentoub One more bad news :)
Using AppendSpanFormattable is slower than original implementation as we use "D4" and "D2" format. And this goes to slow formatting of int : TryFormatInt32Slow

Here are results :
Before

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString79.56 ns1.238 ns0.967 ns79.64 ns77.60 ns81.20 ns0.0486408 B
DateTime_ToString_Local243.25 ns1.684 ns1.576 ns243.55 ns241.02 ns245.91 ns0.0541456 B
DateTime_ToString_Unspecified76.37 ns0.422 ns0.394 ns76.41 ns75.65 ns77.01 ns0.0487408 B
DateTime_ToString_RoundtripKind78.79 ns0.868 ns0.769 ns78.70 ns77.46 ns80.15 ns0.0485408 B
TimeSpan_ToString62.96 ns0.485 ns0.454 ns62.88 ns62.09 ns63.75 ns0.0200168 B

SpanFormattable:

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString129.07 ns1.138 ns1.009 ns129.34 ns125.84 ns129.72 ns0.0131112 B
DateTime_ToString_Local291.06 ns4.934 ns4.615 ns288.28 ns287.16 ns300.48 ns0.0139120 B
DateTime_ToString_Unspecified127.20 ns1.123 ns1.051 ns127.49 ns123.74 ns127.97 ns0.0134112 B
DateTime_ToString_RoundtripKind123.78 ns0.787 ns0.736 ns123.85 ns121.52 ns124.67 ns0.0132112 B
TimeSpan_ToString40.70 ns0.105 ns0.098 ns40.67 ns40.53 ns40.88 ns0.006656 B

Rollback to previous formatting:

MethodMeanErrorStdDevMedianMinMaxGen 0Allocated
DateTime_ToString54.50 ns0.304 ns0.270 ns54.55 ns53.98 ns54.99 ns0.009680 B
DateTime_ToString_Local187.15 ns2.430 ns2.029 ns187.60 ns180.93 ns189.17 ns0.009988 B
DateTime_ToString_Unspecified49.17 ns0.523 ns0.464 ns49.24 ns47.62 ns49.50 ns0.009580 B
DateTime_ToString_RoundtripKind53.01 ns0.768 ns0.718 ns53.34 ns51.73 ns53.67 ns0.009580 B
TimeSpan_ToString41.16 ns0.206 ns0.192 ns41.22 ns40.55 ns41.31 ns0.006556 B

You can use Performance PR for benchmark

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@stephentoub I've pushed changes with previous formatting for D2/4/X of integers as they are much faster. But kept changes for split of AppendSpanFormattable as they seems useful and can be used in other places. Now according benchmarks looks like we have memory + time wins. Are you okay with this changes or I should add something more ?

Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs Outdated
Comment threadsrc/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs Outdated
@TrayanZapryanov

Copy link
Copy Markdown
ContributorAuthor

@danmoseley Is there something more that is expected from me ?

@danmoseley

Copy link
Copy Markdown
Contributor

@stephentoub was your feedback satisfactorily addressed?

@stephentoub

Copy link
Copy Markdown
Member

Thanks.

@TrayanZapryanov

Copy link
Copy Markdown
ContributorAuthor

@danmoseley Once I have one approval, what's next? I see some build errors , but build was not so stable at this time. Should I somehow retrigger? Also who is merging this PR, me or somebody from the team?
Sorry for so stupid questions, but this is my first contribution.

@stephentoub

Copy link
Copy Markdown
Member

Thanks, @TrayanZapryanov. Not stupid questions. We handle merging. I re-ran the failed leg and it passed. Thanks for the contribution.

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

Labels

area-System.Xmlcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Several classes in System.Private.Xml are creating StringBuilders when formatting simple types like DateTime,TimeSpan

5 participants

@TrayanZapryanov@danmoseley@stephentoub@eiriktsarpalis@Trayan-Zapryanov