Skip to content

Speed up KeyAnalyser - #87590

Closed
IDisposable wants to merge 1 commit into
dotnet:mainfrom
IDisposable:faster-freeze-strings
Closed

Speed up KeyAnalyser#87590
IDisposable wants to merge 1 commit into
dotnet:mainfrom
IDisposable:faster-freeze-strings

Conversation

@IDisposable

@IDisposableIDisposable commented Jun 15, 2023

Copy link
Copy Markdown
Contributor

While reviewing #87510 , I noticed the inline code in the Comparers seems like since it's in the hot-loop path, might be faster to move the IsLeft conditionalized code out of the loop by adding a Slicer to the comparator. The Slicer is the same logic as was in the bodies of the Equals and GetHashCode methods, and indeed also matches the delegate that was passed to the internal CreateAnalysisResults method.

NOT SURE if this actually will speed things up at all, hoping to leverage some /azp magic to do the performance evaluations.

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Collections labels Jun 15, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

null

Author:IDisposable
Assignees:-
Labels:

area-System.Collections, community-contribution

Milestone:-

@azure-pipelines

Copy link
Copy Markdown
Supported commands
  • help:
    • Get descriptions, examples and documentation about supported commands
    • Example: help "command_name"
  • list:
    • List all pipelines for this repository using a comment.
    • Example: "list"
  • run:
    • Run all pipelines or specific pipelines for this repository using a comment. Use this command by itself to trigger all related pipelines, or specify specific pipelines to run.
    • Example: "run" or "run pipeline_name, pipeline_name, pipeline_name"
  • where:
    • Report back the Azure DevOps orgs that are related to this repository and org
    • Example: "where"

See additional documentation.

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 87590 in repo dotnet/runtime

@IDisposableIDisposableJun 15, 2023

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.

This is demonstrably true because we're inside the if (ignoreCase) immediately above and could be a distinct PR, but it actually changes nothing but the readability and not hoping the Compiler/JIT groks this truth.

@azure-pipelines

Copy link
Copy Markdown
Commenter does not have sufficient privileges for PR 87590 in repo dotnet/runtime

@IDisposable

Copy link
Copy Markdown
ContributorAuthor

Hey @adamsitnik, can you do the /azp magic to make this run the perf tests?

@adamsitnik

Copy link
Copy Markdown
Member

Hey @adamsitnik, can you do the /azp magic to make this run the perf tests?

I am afraid we don't have that in dotnet/runtime yet (cc @sblom)

For now you need to follow the docs I provided in #87510 (comment) and benchmark it locally

@IDisposable

IDisposable commented Jun 23, 2023

Copy link
Copy Markdown
ContributorAuthor

Sadly @adamsitnik , I can't even get the dotnet/performance stuff to execute at all on my machine... :( dotnet/performance#3096

Fixed that problem by whacking my nuget caches!

@IDisposable
IDisposableforce-pushed the faster-freeze-strings branch 3 times, most recently from 5f231fa to fae39cbCompareJune 29, 2023 05:19
@IDisposable

IDisposable commented Jun 29, 2023

Copy link
Copy Markdown
ContributorAuthor
dotnet run -c Release -f net8.0 \ --filter *Frozen* \
--statisticalTest 2ms \
--coreRun \
"C:\Dev\dotnet\runtime\artifacts\bin\testhost\net8.0-windows-Release-x64\shared\Microsoft.NETCore.App\8.0.0\CoreRun.exe" \
"C:\Dev\dotnet\runtime_baseline\artifacts\bin\testhost\net8.0-windows-Release-x64\shared\Microsoft.NETCore.App\8.0.0\CoreRun.exe"

Initial results from using @adamsitnik benchmarks as of dotnet/performance@28e9ab3

BenchmarkDotNet=v0.13.2.2052-nightly, OS=Windows 11 (10.0.22631.1906)
Intel Core i7-10875H CPU 2.30GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK=8.0.100-preview.7.23322.33
[Host] : .NET 8.0.0 (8.0.23.32106), X64 RyuJIT AVX2
Change: .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2 from IDisposable@fae39cb
Baseline : .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2 from cfae69f

PowerPlanMode=00000000-0000-0000-0000-000000000000 Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true IterationTime=250.0000 ms
MaxIterationCount=20 MinIterationCount=15 WarmupCount=1

MethodToolchainSizeMeanErrorStdDevMedianMinMaxRatioMannWhitney(2ms)AllocatedAlloc Ratio
FrozenDictionaryChange5126.363 us0.0315 us0.0263 us6.364 us6.317 us6.404 us1.00Base-NA
FrozenDictionaryBaseline5126.447 us0.0726 us0.0644 us6.438 us6.360 us6.577 us1.01Same-NA

@IDisposable

IDisposable commented Jun 29, 2023

Copy link
Copy Markdown
ContributorAuthor

So, is a ratio of 1.01 (old code) vs. 1.00 (new code) worthwhile? It isn't slower, and it (to me) is less coupled. Also, I note that the Baseline version has a higher SD and Error, which (to me) means it's more influenced by branch mispredictions.

Also, realized I should have presented the Baseline first in the command, future runs will do so... sorry, learning here.

@IDisposable
IDisposable marked this pull request as ready for review June 29, 2023 07:39
@IDisposable
IDisposableforce-pushed the faster-freeze-strings branch from fae39cb to 42c3414CompareJune 29, 2023 07:56

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.

This encapsulates the login on old line 75

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.

This encapsulates the login on old line 100

@IDisposableIDisposableJun 29, 2023

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.

Here we can just call Slicer, which no longer has an IsLeft conditional test inside a hot loop, so calling through to the GetSpan-like method that was set on lines 60 (for the IsLeft == true logic) and 84 (for the IsLeft == false logic). This (to my reasoning) will result in much better low-level branch-prediction and since the actual delegate bodies are [MethodImpl(MethodImplOptions.AggressiveInlining)] they should be inlined stubs.

We also get to reuse those stubs when we do the construction (instead of "similar" ones coded up for the calls to CreateAnalysisResults)

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 am not confident about the various not-null hints ! that I injected, but I think they're right, if not overkill. Not sure it really would affect the code generated and welcome input on that from low-level ninjas

@IDisposable

Copy link
Copy Markdown
ContributorAuthor

I'm not sure this is an endpoint or a jumping off for more or simply an exploration that should be tabled. I welcome input from @adamsitnik and @MichalStrehovsky or anyone else :)

@IDisposable
IDisposableforce-pushed the faster-freeze-strings branch from 42c3414 to b623d95CompareJuly 5, 2023 21:05
@IDisposable
IDisposableforce-pushed the faster-freeze-strings branch 5 times, most recently from 7745a50 to 2e37d7fCompareJuly 7, 2023 02:18
The slicing is really only changed once per Count, so move the
IsLeft-dependent logic into delegates to see if that makes
things faster.
A little more refactoring
Encourage inlining.
@IDisposable
IDisposableforce-pushed the faster-freeze-strings branch from 2e37d7f to 01da475CompareJuly 7, 2023 03:15
@IDisposable

Copy link
Copy Markdown
ContributorAuthor

Closing this because it's gotten messy

@ghostghost locked as resolved and limited conversation to collaborators Aug 6, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@IDisposable@adamsitnik@eiriktsarpalis