Skip to content

Conversation

majocha
Copy link
Contributor

@majocha majocha commented Sep 27, 2025

Description

Each stack guard thread jump currently spins up a new thread.

This adds metrics to count the jumps by the caller function name. With --times option it could quickly give some limited insight into where the hot paths are.

For example compiling FSC net10.0:

    StackGuard jumps: remapExprImpl: 4507, OptimizeExpr: 1627, accExpr: 866, pushShadowedLocals: 2, accFreeInExprNonLinear: 938, exprF: 12631, CheckExpr: 153 

IcedTasks.Tests:

    |Optimizations                       | 35.4298| 26.1250|   1046|     48|     12|      4|    429|     49|
    ...
    |Write .NET Binary                   | 38.6069|  0.8675|   1161|      1|      0|      0|    410|     51|
    --------------------------------------------------------------------------------------------------------
    ----------------------------------------------------------------------------------------------------------------------------
    | Cache name                          | hit-ratio |     adds |  updates |     hits |   misses | evictions | eviction-fails |
    |-------------------------------------|-----------|----------|----------|----------|----------|-----------|----------------|
    | mostSpecificOverrideMethodInfoCache |    25.00% |        3 |        0 |        1 |        3 |         0 |              0 |
    |             implicitConversionCache |    98.54% |      125 |        0 |     8437 |      125 |         0 |              0 |
    |                     namedItemsCache |    86.57% |     1233 |        0 |     7945 |     1233 |         0 |              0 |
    |                      v_memoize_file |    99.98% |       17 |        0 |   106182 |       17 |         0 |              0 |
    |                   propertyInfoCache |    15.38% |       11 |        0 |        2 |       11 |         0 |              0 |
    |                     methodInfoCache |    79.94% |     4356 |        0 |    17357 |     4356 |         0 |              0 |
    |            entireTypeHierarchyCache |    98.89% |      172 |        0 |    15331 |      172 |         0 |              0 |
    |           recdOrClassFieldInfoCache |     0.00% |        1 |        0 |        0 |        1 |         0 |              0 |
    ----------------------------------------------------------------------------------------------------------------------------
    StackGuard jumps: remapExprImpl: 2076, OptimizeExpr: 23810, exprF: 29464, CheckExpr: 1543 

@github-actions
Copy link
Contributor

github-actions bot commented Sep 27, 2025

⚠️ Release notes required, but author opted out

Warning

Author opted out of release notes, check is disabled for this pull request.
cc @dotnet/fsharp-team-msft

@vzarytovskii
Copy link
Member

I think one-off compilation/stackguard stats are much less interesting than long-running tooling stats. It is exposed via dotnet-counters, right?

@majocha
Copy link
Contributor Author

majocha commented Sep 29, 2025

I think one-off compilation/stackguard stats are much less interesting than long-running tooling stats. It is exposed via dotnet-counters, right?

Yes, this PR also displays the stats live in VS experimental instance.

What is interesting in one-off is the number of thread jumps, much higher than intuitively expected. In fact, switching off the stackguard gives noticeable boost to compilation times (well, unless a SO happens).

@vzarytovskii
Copy link
Member

What is interesting in one-off is the number of thread jumps, much higher than intuitively expected. In fact, switching off the stackguard gives noticeable boost to compilation times (well, unless a SO happens).

Yes, that's why I have attempted to rewrite a bunch of places (like CE checking) to be tailrec from using SG, didn't go well.

@majocha
Copy link
Contributor Author

majocha commented Sep 29, 2025

periodic updates when running VS experimental instance
image

@majocha
Copy link
Contributor Author

majocha commented Sep 29, 2025

What is interesting in one-off is the number of thread jumps, much higher than intuitively expected. In fact, switching off the stackguard gives noticeable boost to compilation times (well, unless a SO happens).

Yes, that's why I have attempted to rewrite a bunch of places (like CE checking) to be tailrec from using SG, didn't go well.

Another approach is to wrap the critical stuff with a trampolining CE, just like some things are already wrapped with cancellable.

@majocha
Copy link
Contributor Author

majocha commented Sep 29, 2025

image

@majocha
Copy link
Contributor Author

majocha commented Sep 29, 2025

Another approach is to wrap the critical stuff with a trampolining CE, just like some things are already wrapped with cancellable.

I attempted this with CheckComputationExpressions but this again hits the bug/limitiation where state machines containing large match clauses can't be statically compiled.

@T-Gro T-Gro added the NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes label Sep 30, 2025
@T-Gro
Copy link
Member

T-Gro commented Sep 30, 2025

I think one-off compilation/stackguard stats are much less interesting than long-running tooling stats. It is exposed via dotnet-counters, right?

Yes, this PR also displays the stats live in VS experimental instance.

What is interesting in one-off is the number of thread jumps, much higher than intuitively expected. In fact, switching off the stackguard gives noticeable boost to compilation times (well, unless a SO happens).

Are the limits too defensive perharps?

Intuitively, we would want to SG limit to be tightly below SO failure, meaning it should not affect perf in the happy path that much (basically just for the wrapper which should be inlined, but with no new thread).

@T-Gro
Copy link
Member

T-Gro commented Sep 30, 2025

That FindUnsolved number of jumps is massive, and I think in there is just about collecting an unsorted list of unsolved type variables (could be replaced with mutation or an explicit queue/stack)

@github-project-automation github-project-automation bot moved this from New to In Progress in F# Compiler and Tooling Sep 30, 2025
@T-Gro T-Gro merged commit 80da32a into dotnet:main Sep 30, 2025
38 of 39 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in F# Compiler and Tooling Sep 30, 2025
@T-Gro
Copy link
Member

T-Gro commented Sep 30, 2025

/backport to release/dev18.0

@github-actions
Copy link
Contributor

Started backporting to release/dev18.0: https://github.com/dotnet/fsharp/actions/runs/18125805609

@vzarytovskii
Copy link
Member

That FindUnsolved number of jumps is massive, and I think in there is just about collecting an unsorted list of unsolved type variables (could be replaced with mutation or an explicit queue/stack)

Yes, it should be relatively easy to rewrite it to explicit stack

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants