This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tiered compilation is a new feature we are experimenting with that aims to improve startup times. Initially we jit methods non-optimized, then switch to an optimized version once the method has been called a number of times. More details about the current feature operation are in the comments of TieredCompilation.cpp. This is only the first step in a longer process building the feature. The primary goal for now is to avoid regressing any runtime behavior in the shipping configuration in which the complus variable is OFF, while putting enough code in place that we can measure performance in the daily builds and make incremental progress visible to collaborators and reviewers. The design of the TieredCompilationManager is likely to change substantively, and the call counter may also change.
- Loading branch information
Showing
23 changed files
with
870 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
// =========================================================================== | ||
// File: CallCounter.CPP | ||
// | ||
// =========================================================================== | ||
|
||
|
||
|
||
#include "common.h" | ||
#include "excep.h" | ||
#include "log.h" | ||
#include "tieredcompilation.h" | ||
#include "callcounter.h" | ||
|
||
#ifdef FEATURE_FITJIT | ||
|
||
CallCounter::CallCounter() | ||
{ | ||
LIMITED_METHOD_CONTRACT; | ||
|
||
m_lock.Init(LOCK_TYPE_DEFAULT); | ||
} | ||
|
||
// Init our connection to the tiered compilation manager during | ||
// AppDomain startup. This pointer will remain valid for the lifetime | ||
// of the AppDomain. | ||
void CallCounter::SetTieredCompilationManager(TieredCompilationManager* pTieredCompilationManager) | ||
{ | ||
CONTRACTL | ||
{ | ||
NOTHROW; | ||
GC_NOTRIGGER; | ||
CAN_TAKE_LOCK; | ||
MODE_PREEMPTIVE; | ||
} | ||
CONTRACTL_END; | ||
|
||
SpinLockHolder holder(&m_lock); | ||
m_pTieredCompilationManager = pTieredCompilationManager; | ||
} | ||
|
||
// This is called by the prestub each time the method is invoked in a particular | ||
// AppDomain (the AppDomain for which AppDomain.GetCallCounter() == this). These | ||
// calls continue until we backpatch the prestub to avoid future calls. This allows | ||
// us to track the number of calls to each method and use it as a trigger for tiered | ||
// compilation. | ||
// | ||
// Returns TRUE if no future invocations are needed (we reached the count we cared about) | ||
// and FALSE otherwise. It is permissible to keep calling even when TRUE was previously | ||
// returned and multi-threaded race conditions will surely cause this to occur. | ||
BOOL CallCounter::OnMethodCalled(MethodDesc* pMethodDesc) | ||
{ | ||
STANDARD_VM_CONTRACT; | ||
|
||
_ASSERTE(pMethodDesc->IsEligibleForTieredCompilation()); | ||
|
||
// PERF: This as a simple to implement, but not so performant, call counter | ||
// Currently this is only called until we reach a fixed call count and then | ||
// disabled. Its likely we'll want to improve this at some point but | ||
// its not as bad as you might expect. Allocating a counter inline in the | ||
// MethodDesc or at some location computable from the MethodDesc should | ||
// eliminate 1 pointer per-method (the MethodDesc* key) and the CPU | ||
// overhead to acquire the lock/search the dictionary. Depending on where it | ||
// is we may also be able to reduce it to 1 byte counter without wasting the | ||
// following bytes for alignment. Further work to inline the OnMethodCalled | ||
// callback directly into the jitted code would eliminate CPU overhead of | ||
// leaving the prestub unpatched, but may not be good overall as it increases | ||
// the size of the jitted code. | ||
|
||
|
||
TieredCompilationManager* pCallCounterSink = NULL; | ||
int callCount; | ||
{ | ||
//Be careful if you convert to something fully lock/interlocked-free that | ||
//you correctly handle what happens when some N simultaneous calls don't | ||
//all increment the counter. The slight drift is probably neglible for tuning | ||
//but TieredCompilationManager::OnMethodCalled() doesn't expect multiple calls | ||
//each claiming to be exactly the threshhold call count needed to trigger | ||
//optimization. | ||
SpinLockHolder holder(&m_lock); | ||
pCallCounterSink = m_pTieredCompilationManager; | ||
|
||
CallCounterEntry* pEntry = const_cast<CallCounterEntry*>(m_methodToCallCount.LookupPtr(pMethodDesc)); | ||
if (pEntry == NULL) | ||
{ | ||
callCount = 1; | ||
m_methodToCallCount.Add(CallCounterEntry(pMethodDesc, callCount)); | ||
} | ||
else | ||
{ | ||
pEntry->callCount++; | ||
callCount = pEntry->callCount; | ||
} | ||
} | ||
|
||
return pCallCounterSink->OnMethodCalled(pMethodDesc, callCount); | ||
} | ||
|
||
#endif // FEATURE_FITJIT |
Oops, something went wrong.