Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Add a unified mechanism to track metadata/metrics about the compilation #98653

Merged
merged 24 commits into from
Feb 21, 2024

Conversation

jakobbotsch
Copy link
Member

@jakobbotsch jakobbotsch commented Feb 19, 2024

Adds a JIT-EE API to report metadata back to the EE side about the JIT compilation, and adds support for saving these metrics as part of SPMI runs. Switches a number of adhoc metrics to use this scheme, and also adds a few new ones.

The metadata is currently only reported with checked JITs.

Also adds support for fast perfscore diffs, and adds perfscore into the reports generated by superpmi.py asmdiffs.

Fix #52877

As future work we should include the metrics as part of the generated diffs report. I think we can do that automatically with relatively little effort. We also may want some variant of superpmi.py replay which just collects the metrics into a report.

The system also reports back the method full name and the tiering name as metadata. We can use this in the future to improve the analysis (in particular, grouping repeated diffs in methods of the same full name + tiering name).

For Andy's use case we may consider reporting the metrics back to the EE even in release builds (maybe only under JitMetrics or something else that SPMI could set).

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 19, 2024
@ghost ghost assigned jakobbotsch Feb 19, 2024
@ghost
Copy link

ghost commented Feb 19, 2024

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Issue Details

Adds a JIT-EE API to report metadata back to the EE side about the JIT compilation, and adds support for saving these metrics as part of SPMI runs. Switches a number of adhoc metrics to use this scheme.

Fix #52877

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

…ilation

Adds a JIT-EE API to report metadata back to the EE side about the JIT
compilation, and adds support for saving these metrics as part of SPMI
runs. Switches a number of adhoc metrics to use this scheme.
Comment on lines +70 to +108
bool FileWriter::PrintQuotedCsvField(const char* value)
{
size_t numQuotes = 0;
for (const char* p = value; *p != '\0'; p++)
{
if (*p == '"')
{
numQuotes++;
}
}

if (numQuotes == 0)
{
return Printf("\"%s\"", value);
}
else
{
size_t len = 2 + strlen(value) + numQuotes;
char* buffer = new char[len];

size_t index = 0;
buffer[index++] = '"';
for (const char* p = value; *p != '\0'; p++)
{
if (*p == '"')
{
buffer[index++] = '"';
}
buffer[index++] = *p;
}

buffer[index++] = '"';
assert(index == len);

bool result = Print(buffer, len);
delete[] buffer;
return result;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Oddly there's a function with full name

System.Xml.Xsl.CompiledQuery.Query:<xsl:template match="Class">(System.Xml.Xsl.Runtime.XmlQueryRuntime,System.Xml.XPath.XPathNavigator,double,double,System.Collections.Generic.IList`1[System.Xml.XPath.XPathNavigator])

in libraries_tests.run, so I had to add this support.

@@ -95,7 +95,7 @@ DLLEXPORT int __cdecl _vsnprintf_s (
retvalue = vsnprintf(string, sizeInBytes, format, ap);
string[sizeInBytes - 1] = '\0';
/* we allow truncation if count == _TRUNCATE */
if (retvalue > (int)sizeInBytes && count == _TRUNCATE)
if (retvalue >= (int)sizeInBytes && count == _TRUNCATE)
Copy link
Member Author

Choose a reason for hiding this comment

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

Will submit this fix separately... it should have a unit test added as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

@jakobbotsch jakobbotsch marked this pull request as ready for review February 20, 2024 18:40
@jakobbotsch
Copy link
Member Author

cc @dotnet/jit-contrib PTAL @BruceForstall @AndyAyersMS

Here is an example for how the new SPMI report looks. I added the "PerfScore in Diffs" column to the main result tables and a "PerfScore Overall (FullOpts)" column in the "Details" tables. The former one specifies the geomean computed over the relative perfscore in every context with diffs; the latter one is the geomean computed over the relative perfscore for all contexts. In other words, the one shown in the main table can be interpreted as "when my optimization kicks in, how much does it affect perf score". The one in the details is more of a "what is the overall impact".

Copy link
Member

@BruceForstall BruceForstall left a comment

Choose a reason for hiding this comment

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

LGTM. Some questions/suggestions.

One additional question: should the metadata info list / schema be statically known (defined in a header file), or dynamic? (clients don't know all the metadata names/types, except maybe by convention, beforehand)

JITMETADATAMETRIC(LoopsAligned, int, 0)
JITMETADATAMETRIC(VarsInSsa, int, 0)
JITMETADATAMETRIC(HoistedExpressions, int, 0)
JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER)
Copy link
Member

Choose a reason for hiding this comment

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

Are the flags used anywhere? Where is JIT_METADATA_HIGHER_IS_BETTER defined? It seems odd to include this file in superpmi source code but not have this defined there.

Copy link
Member Author

Choose a reason for hiding this comment

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

They aren't yet, but my plan was to use this to automatically colorize the metrics in the report (once I add that support). Indeed I haven't defined the enum anywhere yet (and it'll probably only end up being define in superpmi and not the JIT).

Comment on lines +16 to +17
JITMETADATAINFO(MethodFullName, const char*, 0)
JITMETADATAINFO(TieringName, const char*, 0)
Copy link
Member

Choose a reason for hiding this comment

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

What is the difference between JITMETADATAINFO and JITMETADATAMETRIC? (Document above).

Also, the answers to MethodFullName and TieringName are hard coded in SPMI playback. Should that be noted somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added this comment above:

// List of metadata that the JIT can report. There are two categories:
//
// - JITMETADATAINFO: General info that can be of any type and that cannot be
//   aggregated in straightforward ways. These properties are not handled
//   automatically; the JIT must explicitly report them using
//   JitMetadata::report, and the SPMI side needs to manually handle (or ignore)
//   them in ICorJitInfo::reportMetadata.
//
// - JITMETADATAMETRIC: Metrics which are numeric types (currently int, double
//   and int64_t types supported). Their reporting is handled automatically and
//   they will be propagated all the way into SPMI replay/diff results.

//
void JitMetadata::report(Compiler* comp, JitMetadataName name, const void* data)
{
comp->info.compCompHnd->reportMetadata(getName(name), data);
Copy link
Member

Choose a reason for hiding this comment

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

Should the report functions do nothing if RunningSuperPmiReplay() is false? (I guess the VM does nothing anyway)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I figured that we should just let it be up to the EE. If the EE wants to do something with the information then that's up to them. (Also, we don't check for SPMI in release JITs)

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Looks good, Bruce has already covered anything I'd have commented on.

I would like to update JitMetrics to use a variant of this, but there are some vector-valued things there. Hmm.

@jakobbotsch
Copy link
Member Author

jakobbotsch commented Feb 21, 2024

One additional question: should the metadata info list / schema be statically known (defined in a header file), or dynamic? (clients don't know all the metadata names/types, except maybe by convention, beforehand)

I really want the SPMI side to be able to know what metrics to expect beforehand, just because it simplifies things in the csv handling and also allows e.g. superpmi.py to query metadata about the metrics separately, like the "higher is better" info. There may also be other kinds of metadata about the metrics in the future (for example, some metrics make sense to aggregate as sums/averages, while some other metrics may make more sense to aggregate as min/max). I'd like to be able to have one place to define all of this and automatically have it propagate all the way into superpmi.py -- and I was trying to make jitmetadatalist.h that place.

Initially I was going to add a new method to the host interface to be able to get the information about the metrics dynamically. For example, then the JIT side would be the only place we used jitmetadatalist.h, to report this information back. It would probably be slightly more flexible than the current approach, which has some downsides. For example, in the current approach if you change the type of a metric then running superpmi.exe with an old JIT will make it misinterpret the metric data as the new type when the old JIT is reports the old type. However, it seemed much easier to just use jitmetadatalist.h from SPMI always, and I would expect the problematic changes to jitmetadatalist.h to be rare (and if we need to make them we always have the hammer of updating the JIT-EE GUID).

I would like to update JitMetrics to use a variant of this, but there are some vector-valued things there. Hmm.

I added a size_t length arg to the API. That seems like good API hygiene regardless when dealing with void*, and you can use it for your case to report the full array of metadata in one shot (although you're still going to need some manual handling on the SPMI side, but I guess that's inevitable).

@jakobbotsch jakobbotsch merged commit 80084aa into dotnet:main Feb 21, 2024
121 of 125 checks passed
@jakobbotsch jakobbotsch deleted the jit-metrics branch February 21, 2024 10:40
@github-actions github-actions bot locked and limited conversation to collaborators Mar 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SuperPMI asm diffs and metrics improvement
3 participants