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

Simplified MinOpts GC ref tracking.#9231

Merged
pkukol merged 11 commits into
dotnet:masterfrom
pkukol:MinOptsSimplifiedGCtracking
Feb 23, 2017
Merged

Simplified MinOpts GC ref tracking.#9231
pkukol merged 11 commits into
dotnet:masterfrom
pkukol:MinOptsSimplifiedGCtracking

Conversation

@pkukol
Copy link
Copy Markdown

@pkukol pkukol commented Jan 31, 2017

Not ready for "official" review yet, but feel free to look and comment anytime ;).

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Jan 31, 2017

@dotnet-bot test CentOS7.1 gcstress0xc_minopts_heapverify1
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test CentOS7.1 zapdisable
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test OSX gcstress0x3
@dotnet-bot test OSX gcstress0xc
@dotnet-bot test OSX gcstress0xc_minopts_heapverify1
@dotnet-bot test OSX minopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Ubuntu corefx_minopts
@dotnet-bot test Ubuntu gcstress0x3
@dotnet-bot test Ubuntu gcstress0xc
@dotnet-bot test Ubuntu gcstress0xc_jitstress1
@dotnet-bot test Ubuntu gcstress0xc_jitstress2
@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1
@dotnet-bot test Ubuntu minopts
@dotnet-bot test Windows_NT Checked r2r_jitminopts
@dotnet-bot test Windows_NT arm64 Checked gcstress0x3
@dotnet-bot test Windows_NT arm64 Checked gcstress0xc
@dotnet-bot test Windows_NT corefx_minopts
@dotnet-bot test Windows_NT gcstress0xc_minopts_heapverify1
@dotnet-bot test Windows_NT minopts
@dotnet-bot test Windows_NT x86 Checked gcstress0xc_minopts_heapverify1
@dotnet-bot test Windows_NT x86 Checked minopts
@dotnet-bot test Windows_NT zapdisable

@DrewScoggins
Copy link
Copy Markdown
Member

test Windows_NT perf

@DrewScoggins
Copy link
Copy Markdown
Member

test Ubuntu14.04 perf

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 1, 2017

@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test OSX gcstress0x3
@dotnet-bot test OSX gcstress0xc
@dotnet-bot test OSX gcstress0xc_minopts_heapverify1
@dotnet-bot test OSX minopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Ubuntu corefx_minopts
@dotnet-bot test Ubuntu gcstress0x3
@dotnet-bot test Ubuntu gcstress0xc
@dotnet-bot test Ubuntu gcstress0xc_jitstress1
@dotnet-bot test Ubuntu gcstress0xc_jitstress2
@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1
@dotnet-bot test Ubuntu minopts
@dotnet-bot test Windows_NT Checked r2r_jitminopts
@dotnet-bot test Windows_NT arm64 Checked gcstress0x3
@dotnet-bot test Windows_NT arm64 Checked gcstress0xc
@dotnet-bot test Windows_NT corefx_minopts
@dotnet-bot test Windows_NT gcstress0xc_minopts_heapverify1
@dotnet-bot test Windows_NT minopts
@dotnet-bot test Windows_NT x86 Checked gcstress0xc_minopts_heapverify1
@dotnet-bot test Windows_NT x86 Checked minopts
@dotnet-bot test Windows_NT zapdisable

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 1, 2017

@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test Windows_NT x64 Formatting

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 1, 2017

@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Ubuntu corefx_minopts
@dotnet-bot test Ubuntu gcstress0x3
@dotnet-bot test Ubuntu gcstress0xc
@dotnet-bot test Ubuntu gcstress0xc_jitstress1
@dotnet-bot test Ubuntu gcstress0xc_jitstress2
@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1
@dotnet-bot test Ubuntu minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 1, 2017

@dotnet-bot test OSX gcstress0x3
@dotnet-bot test OSX gcstress0xc
@dotnet-bot test OSX gcstress0xc_minopts_heapverify1

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 1, 2017

@dotnet-bot test OSX Checked r2r_jitminopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 2, 2017

@dotnet-bot test Ubuntu minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 3, 2017

@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 3, 2017

@dotnet-bot test CentOS7.1 gcstress0xc
@dotnet-bot test CentOS7.1 gcstress0xc_minopts_heapverify1
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test CentOS7.1 zapdisable

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 3, 2017

@dotnet-bot test Ubuntu minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 12, 2017

@swaroop-sridhar @jkotas @BruceForstall @sivarv PTAL
BTW, I went out of my way to minimize any impact on non-MinOpts paths etc, but this forced some duplication of code etc; if you have any suggestions as far as how to implant the new stuff please let me know - I'd love to share the blame I mean credit with others.

@BruceForstall
Copy link
Copy Markdown

@pkukol Looks like there are a bunch of test failures. Do you still want it reviewed now?

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@BruceForstall Yes please, most of the test failures appear to be spurious or are errors in the tests themselves; I am tracking two strange failures on desktop (one is COBOL and the other one is a complex physics simulation so it's proving to be a bit difficult) but other than that everything passes. Except for some flavors of Linux but I can't tell whether those are genuine failures or not. Still hoping to hear from someone as far as how to run tests on Linux with my build to close that loop. Sorry about that.

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test Ubuntu gcstress0xc_minopts_heapverify1
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test CentOS7.1 gcstress0xc_minopts_heapverify1

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@dotnet-bot test OSX minopts
@dotnet-bot test OSX gcstress0xc_minopts_heapverify1

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@dotnet-bot test OSX gcstress0x3
@dotnet-bot test OSX gcstress0xc_minopts_heapverify1
@dotnet-bot test OSX gcstress0xc
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test OSX Checked r2r
@dotnet-bot test Ubuntu x64 Checked Build and Test
@dotnet-bot test Ubuntu corefx_minopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Windows_NT corefx_minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@dotnet-bot test CentOS7.1 gcstress0xc_minopts_heapverify1
@dotnet-bot test Ubuntu gcstress0xc_jitstress1
@dotnet-bot test Ubuntu gcstress0xc_jitstress2

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 13, 2017

@dotnet-bot test Ubuntu gcstress0x3

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
for (int i = 0; i < 50; i++)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Would it make more sense to create a new DoCollect() function that does these three lines, is marked NoInlining, and is called between the Test1()/Test2()/etc. calls in Main()?

Copy link
Copy Markdown
Author

@pkukol pkukol Feb 14, 2017

Choose a reason for hiding this comment

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

This will be in the next push.

Comment thread src/jit/gcencode.cpp Outdated
GCENCODER_WITH_LOGGING(gcInfoEncoderWithLog, gcInfoEncoder);

#if defined(_TARGET_AMD64_) && defined(FEATURE_CORECLR)
const bool fastPath = (compiler->opts.MinOpts() && !compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) &&
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

fastPath [](start = 15, length = 8)

fastPath seems too generic a name. Why not trackGcRefs or MinOptsTrackGcRefs?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It's actually the opposite so I picked *"noTrackedGCSlots - hope that's OK.

Comment thread src/jit/gcencode.cpp
{
gcInfoEncoderWithLog->DefineCallSites(nullptr, nullptr, 0);
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It's unfortunate and undesirable to add a "return" in the middle of this enormous method. Isn't there a way to restructure the code to avoid this, and let it fall through (without adding too much complexity in the way of additional nesting, etc.)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The main goal is to skip all the code below here because we know (from the first pass) that we'll find no calls that we'll need to record, but there are usually quite a few calls on the list (they just all get skipped twice in 99.9% of the cases). The only way to avoid wrapping everything below in yet another level of nesting would be to bash the call list to null but that seems extremely dirty (and may not work). If you have a specific idea, though, please let me know - I agree the method is pretty knarly as it is.

Comment thread src/jit/jitconfigvalues.h Outdated
#endif // !defined(DEBUG) && !defined(_DEBUG)

#if defined(_TARGET_AMD64_) && defined(FEATURE_CORECLR)
CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), 0) // Allow GC roots to be tracked w/MinOpts
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why is this feature for AMD64 only? And why only CoreCLR? You can set the defaults for that, if you are worried about changing existing behavior. So, shouldn't it be:

#if !defined(JIT32_GCENCODER)
#if defined(_TARGET_AMD64_) && defined(FEATURE_CORECLR)
#define JitMinOptsTrackGCrefs_Default 0 // Not tracking GC refs in MinOpts is new behavior
#else
#define JitMinOptsTrackGCrefs_Default 1
#endif
CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), JitMinOptsTrackGCrefs_Default) // If non-zero, allow GC roots to be tracked w/MinOpts
#endif // !defined(JIT32_GCENCODER)

Copy link
Copy Markdown
Author

@pkukol pkukol Feb 14, 2017

Choose a reason for hiding this comment

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

Hmm, hold on - are you suggesting we ditch all the #ifdef's as well? That's not as obvious because even if it's normally disabled, it adds a bunch of code (mostly only 'if' statements but still) but more importantly in the GC decoder it weakens an assert that I think is quite important (I wanted to add an explicit bit, so that we don't have to assume that we see the new behavior by the absence of some stuff we normally require to be present, but there's no obvious place for a new flag, plus nobody else though it was worth a flag anyway). The suggestion to keep it out of the non-CORECLR build came from the VM folks so how about I leave it the way it is, since it's only been tested that way, and once it's proven its worth (which has yet to be verified independently) it can be enabled in more places?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, I was suggesting eliminating all the #ifdefs, so it would be possible to enable and test on desktop, or on non-AMD64 platforms, simply by setting a COMPlus variable. We have very few #ifdef FEATURE_CORECLR and I'd like to keep it that way.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Missed your second comment until now; sorry about that. OK, I will change this as you suggest, but it still leaves the issue of the assert in vm\gcinfodecode.cpp - assuming it can see the above flag (the whole CLR vs. JIT config flags thing is still a mystery to me), it will need to test the flag when decoding GC info (at runtime) or we just weaken the decoding assert for every config / all the time? Neither approach seems ideal to me, but there's probably a way to do this better that I'm not seeing; please bear with me.

And, just to make absolutely sure - with this newest change, the new code will always be compiled in and we'll use a runtime test of (pseudo-code) config.JitMinOptsTrackGCrefs in the various spots in the *.cpp files instead of switching the code out completely (using the current "#ifdef AMD64 && blah blah"); correct?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

clrconfigvalues.h is for things read by the VM; jitconfigvalues.h is for things read by the VM. Note that clrconfigvalues.h does duplicate many things, if those things are used by JIT32/JIT64, which does not have jitconfigvalues.h and that mechanism. That is usually what causes confusion.

Yes, there will be code dynamically executed because of this, but presumably it will be very small/cheap.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Should be done now - @BruceForstall kindly TAL.

Comment thread src/vm/gcinfodecoder.cpp
// No ranges and no explicit safepoint - must be MinOpts.
noTrackedRefs = true;
goto NO_RANGES;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can you please figure out a way to avoid adding this goto?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

That's trivial to do (and I've tried it both ways) but when I asked earlier no feedback resulted so I left it alone; will do it by adding an 'if', then.

Comment thread src/jit/lclvars.cpp Outdated

/* static */
int __cdecl Compiler::WtdRefCntCmpSimpleGC(const void* op1, const void* op2)
{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Please add a new standard-format function header.

You don't care about weighted ref counts in this case, right?, so why is it named "Wtd..."?

In fact, couldn't you assert:

assert(!dsc1->lvTracked);
assert(!dsc2->lvTracked);

?

So the only thing you are doing is sorting GC refs together?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Decided to ditch this thing, it's just too awkward and ugly (and a maintenance danger); thanks for flagging it.

Comment thread src/jit/lclvars.cpp Outdated
}

// TODO(REVIEW): if we're here it means we have MinOpts and "simplified
// GC tracking", so we may be able to prune the stuff that follows.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems correct to me, if you add the assert I suggest.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It seems like you should secondarily sort on weights, after GC-ness, before falling back to lclvar number to break ties.

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 14, 2017

@swaroop-sridhar @jkotas @BruceForstall @sivarv @pgavlin PTanotherL
I think I've addressed all the comments / suggestions; if you happen to spot something I've missed please let me know (and I do apologize). And, of course, any additional feedback is always welcome.

Comment thread src/jit/lclvars.cpp Outdated
else if (opts.MinOpts() && !JitConfig.JitMinOptsTrackGCrefs())
{
if (varTypeIsGC(varDsc->TypeGet()))
{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

minor: you may want all the conditions on the "else if" line above. Otherwise, if someone adds yet another "else if" case below, then it wouldn't get hit for the minopts & !JitMinOptsTrackGCrefs() case if the var isn't GC.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point - in my testing version there's actually another statement in there so the two if's need to be separate but in the "real" version it's simple and might as well combine the conditions. Good catch, will include it in my next push.

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 15, 2017

@dotnet-bot test OSX minopts
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test Ubuntu minopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Windows_NT minopts
@dotnet-bot test Windows_NT Checked r2r_jitminopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 15, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test Windows_NT minopts

2 similar comments
@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 16, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test Windows_NT minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 17, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test Windows_NT minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 18, 2017

@dotnet-bot test OSX minopts
@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Windows_NT Checked r2r_jitminopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 20, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test Windows_NT minopts

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 23, 2017

@dotnet-bot test Ubuntu minopts
@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test Windows_NT minopts

@BruceForstall
Copy link
Copy Markdown

LGTM. Please squash commits before merging.

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 23, 2017

@dotnet-bot test CentOS7.1 minopts
@dotnet-bot test OSX x64 Checked Build and Test
@dotnet-bot test Ubuntu minopts
@dotnet-bot test Ubuntu x64 Checked Build and Test

@pkukol
Copy link
Copy Markdown
Author

pkukol commented Feb 23, 2017

@dotnet-bot test OSX Checked r2r_jitminopts
@dotnet-bot test Ubuntu Checked r2r_jitminopts
@dotnet-bot test Windows_NT Checked r2r_jitminopts

@pkukol pkukol merged commit d7509df into dotnet:master Feb 23, 2017
@pkukol pkukol deleted the MinOptsSimplifiedGCtracking branch February 23, 2017 16:13
jorive pushed a commit to guhuro/coreclr that referenced this pull request May 4, 2017
Simplified MinOpts GC ref tracking - when a method is compiled with MinOpts for targets with the 64-bit GC info encoder we mark all GC slots as untracked and we omit encoding call sites with no live tracked GC refs explicitly in the GC tables; this can be controlled using the new COMPlus_JitMinOptsTrackGCrefs environment flag.
@karelz karelz modified the milestone: 2.0.0 Aug 28, 2017
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Simplified MinOpts GC ref tracking - when a method is compiled with MinOpts for targets with the 64-bit GC info encoder we mark all GC slots as untracked and we omit encoding call sites with no live tracked GC refs explicitly in the GC tables; this can be controlled using the new COMPlus_JitMinOptsTrackGCrefs environment flag.


Commit migrated from dotnet/coreclr@d7509df
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants