Skip to content

Commit

Permalink
JIT: Enhance metrics reported by superpmi diffs
Browse files Browse the repository at this point in the history
* Report the total number of contexts, minopts contexts and fullopts
  contexted processed
* Report number of successful and missing contexts
* Report asmdiffs and tpdiffs for minopts/fullopts separately

Fixes dotnet#70350
Contributes to dotnet#73506
  • Loading branch information
jakobbotsch committed Aug 25, 2022
1 parent 706953d commit ba7bd0c
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 165 deletions.
200 changes: 151 additions & 49 deletions src/coreclr/scripts/superpmi.py

Large diffs are not rendered by default.

35 changes: 2 additions & 33 deletions src/coreclr/scripts/superpmi_diffs_summarize.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,8 @@ def append_diff_file(f, arch, file_name, full_file_path, asmdiffs):
else:
diffs_found = True
f.write("## {} {}\n".format(diff_os, diff_arch))

if asmdiffs:
# Contents of asmdiffs are large so create a
# <summary><details> ... </details> disclosure section around
# the file and additionally provide some instructions.
f.write("""\
<details>
<summary>{0} {1} details</summary>
Summary file: `{2}`
To reproduce these diffs on Windows {3}:
```
superpmi.py asmdiffs -target_os {0} -target_arch {1} -arch {3}
```
""".format(diff_os, diff_arch, file_name, arch))

# Now write the contents
f.write(contents)

# Write the footer (close the <details> section)
f.write("""\
</details>
""")

else:
f.write(contents)
f.write("\n")
f.write(contents)
f.write("\n")

return diffs_found

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,7 @@ DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
DEBUG_REP(dmpGetJitFlags(0, value));

CORJIT_FLAGS* resultFlags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A);
Assert(sizeInBytes >= value.B);
memcpy(jitFlags, resultFlags, value.B);
InitReadyToRunFlag(resultFlags);
return value.B;
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/tools/superpmi/superpmi/jitinstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ extern "C" DLLEXPORT NOINLINE void Instrumentor_GetInsCount(UINT64* result)
}
}

JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, MetricsSummary* metrics)
JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, MetricsSummary* metrics, CORJIT_FLAGS* jitFlags)
{
struct Param : FilterSuperPMIExceptionsParam_CaptureException
{
Expand All @@ -309,13 +309,15 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i
int mcIndex;
bool collectThroughput;
MetricsSummary* metrics;
CORJIT_FLAGS* jitFlags;
} param;
param.pThis = this;
param.result = RESULT_SUCCESS; // assume success
param.flags = 0;
param.mcIndex = mcIndex;
param.collectThroughput = collectThroughput;
param.metrics = metrics;
param.jitFlags = jitFlags;

// store to instance field our raw values, so we can figure things out a bit later...
mc = MethodToCompile;
Expand All @@ -335,6 +337,7 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i
CORINFO_OS os = CORINFO_WINNT;

pParam->pThis->mc->repCompileMethod(&pParam->info, &pParam->flags, &os);
pParam->pThis->mc->repGetJitFlags(pParam->jitFlags, sizeof(*pParam->jitFlags));
if (pParam->collectThroughput)
{
pParam->pThis->lt.Start();
Expand Down Expand Up @@ -436,7 +439,6 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i
{
metrics->SuccessfulCompiles++;
metrics->NumExecutedInstructions += static_cast<long long>(insCountAfter - insCountBefore);

}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/superpmi/superpmi/jitinstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class JitInstance

bool resetConfig(MethodContext* firstContext);

Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, class MetricsSummary* summary);
Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, struct MetricsSummary* metrics, class CORJIT_FLAGS* jitFlags);

const WCHAR* getForceOption(const WCHAR* key);
const WCHAR* getOption(const WCHAR* key);
Expand Down
173 changes: 121 additions & 52 deletions src/coreclr/tools/superpmi/superpmi/metricssummary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@
#include "metricssummary.h"
#include "logging.h"

struct HandleCloser
void MetricsSummary::AggregateFrom(const MetricsSummary& other)
{
void operator()(HANDLE hFile)
{
CloseHandle(hFile);
}
};
SuccessfulCompiles += other.SuccessfulCompiles;
FailingCompiles += other.FailingCompiles;
MissingCompiles += other.MissingCompiles;
NumCodeBytes += other.NumCodeBytes;
NumDiffedCodeBytes += other.NumDiffedCodeBytes;
NumExecutedInstructions += other.NumExecutedInstructions;
NumDiffExecutedInstructions += other.NumDiffExecutedInstructions;
}

void MetricsSummaries::AggregateFrom(const MetricsSummaries& other)
{
Total.AggregateFrom(other.Total);
MinOpts.AggregateFrom(other.MinOpts);
Opts.AggregateFrom(other.Opts);
}

struct FileHandleWrapper
{
Expand All @@ -31,37 +41,61 @@ struct FileHandleWrapper
HANDLE hFile;
};

bool MetricsSummary::SaveToFile(const char* path)
static bool FilePrintf(HANDLE hFile, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);

char buffer[4096];
int len = vsprintf_s(buffer, fmt, args);
DWORD numWritten;
bool result =
WriteFile(hFile, buffer, static_cast<DWORD>(len), &numWritten, nullptr) && (numWritten == static_cast<DWORD>(len));

va_end(args);

return result;
}

bool MetricsSummaries::SaveToFile(const char* path)
{
FileHandleWrapper file(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
if (file.get() == INVALID_HANDLE_VALUE)
{
return false;
}

char buffer[4096];
int len =
sprintf_s(
buffer, sizeof(buffer),
"Successful compiles,Failing compiles,Missing compiles,Code bytes,Diffed code bytes,Executed instructions,Diff executed instructions\n"
"%d,%d,%d,%lld,%lld,%lld,%lld\n",
SuccessfulCompiles,
FailingCompiles,
MissingCompiles,
NumCodeBytes,
NumDiffedCodeBytes,
NumExecutedInstructions,
NumDiffExecutedInstructions);
DWORD numWritten;
if (!WriteFile(file.get(), buffer, static_cast<DWORD>(len), &numWritten, nullptr) || numWritten != static_cast<DWORD>(len))
if (!FilePrintf(
file.get(),
"Successful compiles,Failing compiles,Missing compiles,"
"Code bytes,Diffed code bytes,Executed instructions,Diff executed instructions,Name\n"))
{
return false;
}

return true;
return
WriteRow(file.get(), "Total", Total) &&
WriteRow(file.get(), "MinOpts", MinOpts) &&
WriteRow(file.get(), "Opts", Opts);
}

bool MetricsSummaries::WriteRow(HANDLE hFile, const char* name, const MetricsSummary& summary)
{
return
FilePrintf(
hFile,
"%d,%d,%d,%lld,%lld,%lld,%lld,%s\n",
summary.SuccessfulCompiles,
summary.FailingCompiles,
summary.MissingCompiles,
summary.NumCodeBytes,
summary.NumDiffedCodeBytes,
summary.NumExecutedInstructions,
summary.NumDiffExecutedInstructions,
name);
}

bool MetricsSummary::LoadFromFile(const char* path, MetricsSummary* metrics)
bool MetricsSummaries::LoadFromFile(const char* path, MetricsSummaries* metrics)
{
FileHandleWrapper file(CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
if (file.get() == INVALID_HANDLE_VALUE)
Expand All @@ -76,38 +110,73 @@ bool MetricsSummary::LoadFromFile(const char* path, MetricsSummary* metrics)
}

DWORD stringLen = static_cast<DWORD>(len.QuadPart);
std::vector<char> content(stringLen + 1);
std::vector<char> content(stringLen);
DWORD numRead;
if (!ReadFile(file.get(), content.data(), stringLen, &numRead, nullptr) || numRead != stringLen)
if (!ReadFile(file.get(), content.data(), stringLen, &numRead, nullptr) || (numRead != stringLen))
{
return false;
}

content[stringLen] = '\0';

int scanResult =
sscanf_s(
content.data(),
"Successful compiles,Failing compiles,Missing compiles,Code bytes,Diffed code bytes,Executed instructions,Diff executed instructions\n"
"%d,%d,%d,%lld,%lld,%lld,%lld\n",
&metrics->SuccessfulCompiles,
&metrics->FailingCompiles,
&metrics->MissingCompiles,
&metrics->NumCodeBytes,
&metrics->NumDiffedCodeBytes,
&metrics->NumExecutedInstructions,
&metrics->NumDiffExecutedInstructions);

return scanResult == 7;
}
std::vector<char> line;
size_t index = 0;
auto nextLine = [&line, &content, &index]()
{
size_t end = index;
while ((end < content.size()) && (content[end] != '\r') && (content[end] != '\n'))
{
end++;
}

void MetricsSummary::AggregateFrom(const MetricsSummary& other)
{
SuccessfulCompiles += other.SuccessfulCompiles;
FailingCompiles += other.FailingCompiles;
MissingCompiles += other.MissingCompiles;
NumCodeBytes += other.NumCodeBytes;
NumDiffedCodeBytes += other.NumDiffedCodeBytes;
NumExecutedInstructions += other.NumExecutedInstructions;
NumDiffExecutedInstructions += other.NumDiffExecutedInstructions;
line.resize(end - index + 1);
memcpy(line.data(), &content[index], end - index);
line[end - index] = '\0';

index = end;
if ((index < content.size()) && (content[index] == '\r'))
index++;
if ((index < content.size()) && (content[index] == '\n'))
index++;
};

*metrics = MetricsSummaries();
nextLine();
bool result = true;
while (index < content.size())
{
nextLine();
MetricsSummary summary;

char name[32];
int scanResult =
sscanf_s(
line.data(),
"%d,%d,%d,%lld,%lld,%lld,%lld,%s",
&summary.SuccessfulCompiles,
&summary.FailingCompiles,
&summary.MissingCompiles,
&summary.NumCodeBytes,
&summary.NumDiffedCodeBytes,
&summary.NumExecutedInstructions,
&summary.NumDiffExecutedInstructions,
name, (unsigned)sizeof(name));

if (scanResult == 8)
{
MetricsSummary* tarSummary = nullptr;
if (strcmp(name, "Total") == 0)
metrics->Total = summary;
else if (strcmp(name, "MinOpts") == 0)
metrics->MinOpts = summary;
else if (strcmp(name, "Opts") == 0)
metrics->Opts = summary;
else
result = false;
}
else
{
result = false;
}
}

return result;
}
20 changes: 16 additions & 4 deletions src/coreclr/tools/superpmi/superpmi/metricssummary.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
#ifndef _MetricsSummary
#define _MetricsSummary

class MetricsSummary
struct MetricsSummary
{
public:
// Number of methods successfully jitted.
int SuccessfulCompiles = 0;
// Number of methods that failed jitting.
Expand All @@ -23,9 +22,22 @@ class MetricsSummary
// Number of executed instructions inside contexts that were successfully diffed.
long long NumDiffExecutedInstructions = 0;

bool SaveToFile(const char* path);
static bool LoadFromFile(const char* path, MetricsSummary* metrics);
void AggregateFrom(const MetricsSummary& other);
};

class MetricsSummaries
{
public:
MetricsSummary Total;
MetricsSummary MinOpts;
MetricsSummary Opts;

void AggregateFrom(const MetricsSummaries& other);

bool SaveToFile(const char* path);
static bool LoadFromFile(const char* path, MetricsSummaries* metrics);
private:
static bool WriteRow(HANDLE hFile, const char* name, const MetricsSummary& summary);
};

#endif
Loading

0 comments on commit ba7bd0c

Please sign in to comment.