Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

When QuickJit is enabled, disable it for methods that contain loops by default #24252

Merged
merged 5 commits into from
May 2, 2019

Conversation

kouvel
Copy link
Member

@kouvel kouvel commented Apr 25, 2019

Fixes https://github.com/dotnet/coreclr/issues/19751 by default when QuickJit is enabled

  • Added config variable TC_QuickJitForLoops. When disabled (the default), the JIT identifies loops and explicit tail calls and switches to tier 1 JIT.
  • This would prevent the possibility of spending too long in QuickJit code, but may decrease startup time a bit when QuickJit is enabled
  • Removed TC_StartupTier_OptimizeCode, as now that there is TC_QuickJit, I didn't see a good use for it
  • Removed references to "StartupTier" in config variables because we had previously decided not to call it that.
  • When QuickJit is disabled, avoid creating native code slots for methods in non-R2R'ed modules, as tiering would be disabled for those anyway

…y default

Fixes https://github.com/dotnet/coreclr/issues/19751 by default when QuickJit is enabled
- Added config variable TC_QuickJitForLoops. When disabled (the default), the JIT identifies loops and explicit tail calls and switches to tier 1 JIT.
- This would prevent the possibility of spending too long in QuickJit code, but may decrease startup time a bit when QuickJit is enabled
- Removed TC_StartupTier_OptimizeCode, as now that there is TC_QuickJit, I didn't see a good use for it
- Removed references to "StartupTier" in config variables because we had previously decided not to call it that.
- When QuickJit is disabled, avoid creating native code slots for methods in non-R2R'ed modules, as tiering would be disabled for those anyway
@kouvel kouvel added this to the 3.0 milestone Apr 25, 2019
@kouvel kouvel self-assigned this Apr 25, 2019
`TC_StartupTier_CallCountThreshold` | Number of times a method must be called in the startup tier after which it is promoted to the next tier. | `DWORD` | `UNSUPPORTED` | `30` |
`TC_StartupTier_DelaySingleProcMultiplier` | Multiplier for TC_StartupTier_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor. | `DWORD` | `UNSUPPORTED` | `10` |
`TC_StartupTier_OptimizeCode` | Use optimized codegen (normally used by the optimized tier) in the startup tier | `DWORD` | `INTERNAL` | `0` |
`TC_QuickJitForLoops` | When quick JIT is enabled, quick JIT may also be used for methods that contain loops. | `DWORD` | `UNSUPPORTED` | `0` |
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be EXTERNAL?

Copy link
Member

Choose a reason for hiding this comment

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

(same for TC_QuickJit?)

Copy link
Member Author

Choose a reason for hiding this comment

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

I think TC_QuickJit should be "external" to indicate that it is supported. For TC_QuickJitForLoops, "unsupported" is probably appropriate. It doesn't affect whether the options can be configured with any means.

@kouvel
Copy link
Member Author

kouvel commented Apr 25, 2019

Below are some startup time perf numbers. No significant difference to steady-state perf.

  • Lower is better
  • Tier,NoQJ - current default mode
  • Tier,QJ,NoQJL - QuickJit enabled for methods that don't contain loops - After this change, this is the mode used when QuickJit is enabled
  • Tier,QJ,QJL - QuickJit enabled for all methods - Before this change, this is the mode used when QuickJit is enabled
  • Diffs are against the current default mode (Tier,NoQJ) so that it is easy to see what change is seen when an optional mode is used

JitBench startup times (ms)

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
DotNetBuildHelloWorld 1344.25 1386.67 1328.75 1290.38
CscHelloWorld 568.13 578.38 530.75 483.13
CscRoslynSource 2231.63 2344.80 2312.38 2252.50
EmptyConsoleProgram 62.86 63.50 61.13 62.38
MusicStoreStartup 604.13 615.57 589.13 560.13
MusicStoreFirstRequest 533.63 548.00 457.13 409.50

Diff from Tier,NoQJ:

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
DotNetBuildHelloWorld -3.06% 0.00% -4.18% -6.94%
CscHelloWorld -1.77% 0.00% -8.23% -16.47%
CscRoslynSource -4.83% 0.00% -1.38% -3.94%
EmptyConsoleProgram -1.01% 0.00% -3.74% -1.77%
MusicStoreStartup -1.86% 0.00% -4.30% -9.01%
MusicStoreFirstRequest -2.62% 0.00% -16.58% -25.27%

PowerShell startup times (ms)

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
Startup (pwsh -c exit) 343.70 350.56 343.84 328.17

Diff from Tier,NoQJ:

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
Startup (pwsh -c exit) 0.00% 2.00% 0.04% -4.52%

ASP.NET startup times (server start + first request, ms)

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
DbFortunesEf Windows 1783.16 1833.70 1547.62 1282.57
DbFortunesEf Linux 1774.85 1823.57 1525.10 1253.31
DbFortunesRaw Windows 1064.10 1074.16 972.62 839.72
DbFortunesRaw Linux 1100.03 1102.17 994.59 828.14
Json Windows 565.31 586.11 539.14 516.31
Json Linux 518.77 525.45 471.86 417.72
MvcJson Windows 735.69 758.05 676.88 654.59
MvcJson Linux 671.86 691.51 614.09 547.66
MvcPlaintext Windows 656.82 666.21 620.26 581.36
MvcPlaintext Linux 611.49 627.18 558.31 506.87
Plaintext Windows 487.44 501.95 457.81 421.02
Plaintext Linux 427.12 435.44 383.82 348.57

Diff from Tier,NoQJ:

  NoTier Tier,NoQJ Tier,QJ,NoQJL Tier,QJ,QJL
DbFortunesEf Windows -2.76% 0.00% -15.60% -30.06%
DbFortunesEf Linux -2.67% 0.00% -16.37% -31.27%
DbFortunesRaw Windows -0.94% 0.00% -9.45% -21.83%
DbFortunesRaw Linux -0.19% 0.00% -9.76% -24.86%
Json Windows -3.55% 0.00% -8.01% -11.91%
Json Linux -1.27% 0.00% -10.20% -20.50%
MvcJson Windows -2.95% 0.00% -10.71% -13.65%
MvcJson Linux -2.84% 0.00% -11.20% -20.80%
MvcPlaintext Windows -1.41% 0.00% -6.90% -12.74%
MvcPlaintext Linux -2.50% 0.00% -10.98% -19.18%
Plaintext Windows -2.89% 0.00% -8.79% -16.12%
Plaintext Linux -1.91% 0.00% -11.85% -19.95%

@kouvel kouvel requested review from noahfalk and AndyAyersMS April 25, 2019 19:07
@kouvel
Copy link
Member Author

kouvel commented Apr 29, 2019

@dotnet-bot test Windows_NT x64 Formatting
test Windows_NT x64 Release CoreFX Tests

@kouvel
Copy link
Member Author

kouvel commented Apr 29, 2019

@dotnet-bot test Windows_NT x64 Release CoreFX Tests

@kouvel
Copy link
Member Author

kouvel commented Apr 30, 2019

@dotnet/jit-contrib, would anyone like to take a look at the changes on the JIT side?

@briansull
Copy link

From the data presented it appears that always using QuickJit produces even better startup times:

  • Tier,QJ,QJL - QuickJit enabled for all methods - Before this change, this is the mode used when QuickJit is enabled

Is there some data that supports not using QuickJit for methods that (might) contain loops?

@kouvel
Copy link
Member Author

kouvel commented Apr 30, 2019

It's usually better to enable QuickJit for methods that contain loops. Sometimes though the loop can run for a long time and it would not be optimized ever, or may be optimized late. This usually shows up in simple microbenchmarks, such as the test case in https://github.com/dotnet/coreclr/issues/19751. It can also show up when using BenchmarkDotNet if each invocation of the test takes long enough for BDN to run only a few invocations per iteration. It can happen in non-benchmark code where a method may only run once, like Main or the start method of a long-running thread with an infinite loop. Several workarounds were provided for this issue (AggressiveOptimization attribute, config switches). The issue is showing up frequently with people using 3.0 preview builds and the change is being made to limit risk of the known issue for which we don't have a good solution at the moment.

Copy link

@CarolEidt CarolEidt left a comment

Choose a reason for hiding this comment

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

I have some suggestions for names that I think might be clearer, but am happy to hear arguments to keep them as-is. I'd also like to see function header comments.

src/inc/corinfo.h Outdated Show resolved Hide resolved
src/inc/corinfo.h Outdated Show resolved Hide resolved
src/jit/compiler.h Outdated Show resolved Hide resolved
src/jit/flowgraph.cpp Outdated Show resolved Hide resolved
src/jit/flowgraph.cpp Outdated Show resolved Hide resolved
src/jit/flowgraph.cpp Outdated Show resolved Hide resolved
src/jit/flowgraph.cpp Outdated Show resolved Hide resolved
@kouvel kouvel requested a review from CarolEidt May 2, 2019 20:29
@kouvel kouvel merged commit 607c8db into dotnet:master May 2, 2019
@kouvel kouvel deleted the QjNoLoops branch May 2, 2019 20:48
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
…y default (dotnet/coreclr#24252)

When QuickJit is enabled, disable it for methods that contain loops by default

Fixes https://github.com/dotnet/coreclr/issues/19751 by default when QuickJit is enabled
- Added config variable TC_QuickJitForLoops. When disabled (the default), the JIT identifies loops and explicit tail calls and switches to tier 1 JIT.
- This would prevent the possibility of spending too long in QuickJit code, but may decrease startup time a bit when QuickJit is enabled
- Removed TC_StartupTier_OptimizeCode, as now that there is TC_QuickJit, I didn't see a good use for it
- Removed references to "StartupTier" in config variables because we had previously decided not to call it that.
- When QuickJit is disabled, avoid creating native code slots for methods in non-R2R'ed modules, as tiering would be disabled for those anyway
- Marked TC_QuickJit config var as external

Commit migrated from dotnet/coreclr@607c8db
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[TieredCompilation] Cold methods with hot loops may run slower with tiering
6 participants