Don't re-instrument methods which don't need that#84772
Don't re-instrument methods which don't need that#84772EgorBo wants to merge 3 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue DetailsCloses #84517 static void Main()
{
for (int i = 0; i < 100; i++)
{
Test1();
var _ = Test2;
Thread.Sleep(16);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static int Test1()
{
int sum = 0;
for (int i = 0; i < 1000; i++)
sum += i;
return sum;
}
static int Test2 { get; set; }Was: Now:
|
|
/azp run runtime-coreclr pgo, runtime-coreclr libraries-pgo |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
PTAL @AndyAyersMS thoughts on the approach? |
|
Seems like you perhaps should keep this "don't need to instrument" bit on the NativeCodeVersion instead of the MethodDesc? |
|
I agree with Andy. |
|
Thanks! Looks like it has plenty of space considering that PS: changed it to: |
|
/azp run runtime-coreclr pgo, runtime-coreclr libraries-pgo |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
Moved to NativeCodeVersion, failures are #84798 |
AndyAyersMS
left a comment
There was a problem hiding this comment.
Changes LGTM, but I wonder...
Can we see the same effect with simple R2R methods? That is, would we do R2R -> Tier1 + instr -> Tier1 even if Tier1+instr did not add any probes because the method was trivial?
I wonder if a simpler way of detecting these cases is for the jit interface to track if a schema was created during jitting (that is, if allocPgoInstrumentationBySchema ever got called during this jit attempt).
- If at Tier0 with allow eager instrumentation flag, and the JIT created a schema, bypass future instrumentation requests (JIT decided to do eager instrumentation)
- If at Tier1 BBINSTR and the JIT did not create a schema when the VM requested one, then the current code is Tier1 quality, and so will not benefit from more rejitting.
This would consolidate the logic on the VM side.
|
Ah, interesting idea, I'll try |
957fe5a to
78efc23
Compare
|
libraries-pgo was green last I looked, so maybe fire off that or some other pgo stress leg? |
|
/azp run runtime-coreclr pgo, runtime-coreclr libraries-pgo, runtime-coreclr pgostress |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
@jkotas do vm changes look good to you to merge? |
|
@kouvel Could you please take a look? |
| } | ||
|
|
||
| // Leave a note that this method is properly instrumented | ||
| currentVersion.SetInstrumented(); |
There was a problem hiding this comment.
NativeCodeVersion is a simple wrapper around either a MethodDesc or a NativeCodeVersionNode, and is typically passed by value. The default native code version doesn't have a node and just wraps a MethodDesc. So, it's not a good candidate for persistent storage of this type of info. This change to the code version would just modify the local copy and would not be persisted anywhere.
AFAIK there isn't a clear place currently where such info could be stored. CallCountingInfo may be a candidate, for instance see CallCountingManager::DisableCallCounting() and CallCountingInfo::CreateWithCallCountingDisabled(), which are used to indicate that a code version should not be tiered. However, currently it's not set up to store extra info aside from call counting, for example CallCountingManager::SetCodeEntryPoint() does something different if the CallCountingInfo already exists as opposed to when it's being created. It may be possible to enable precreating a CallCountingInfo for a code version by introducing a new CallCountingInfo::Stage something like NotStarted to indicate that call counting has not started, and to modify SetCodeEntryPoint() to do something similar to before in that case. If the CallCountingInfo already exists, it could be used as persistent storage, as the CallCountingManager has a hash table mapping a code version to a CallCountingInfo.
There was a problem hiding this comment.
Maybe it's better to rollback to occupying a spare bit in MethodDesc m_flag2 then? This change is a sort of an optimization, not correctness. The problem with CallCountingStubs that they're created assyncronlsy like you pointed out
There was a problem hiding this comment.
The info appears to be specific to a code version rather than a method desc, so I'm not sure the method desc would be an appropriate place for it
|
|
||
| private: | ||
|
|
||
| enum NativeCodeVersionFlag : UINT16 |
There was a problem hiding this comment.
I suggest using an enum class to avoid polluting the parent namespace, though this may need to be moved based on my other comment.
| CodeVersionManager* pCodeVersionManager = m_pMethodBeingCompiled->GetCodeVersionManager(); | ||
| CodeVersionManager::LockHolder codeVersioningLockHolder; | ||
| ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(m_pMethodBeingCompiled); | ||
| NativeCodeVersion currentVersion = ilVersion.GetActiveNativeCodeVersion(m_pMethodBeingCompiled); |
There was a problem hiding this comment.
The active code version may have changed meanwhile, so it may not represent the current code version being jitted. Could use something like this instead:
runtime/src/coreclr/vm/jitinterface.cpp
Line 6681 in 7b662a7
Along with config->GetCodeVersion().
|
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
Closes #84517
Was:
Now:
What happened:
get_Test2()is not promoted to Tier0-Instrumented since Tier0 realized it's too simple for that so it's promoted to Tier1 (it's also not needed here but that is a different issue)Test1()promoted itself to Tier0-Instrumented due to loops so it also now tells vm it doesn't need to be promoted to Tier0-Instrumented again (and discard OSR versions)