From 3ea9961d8e0a5ed6a165f27bb3f73a2394ad8253 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 12 Oct 2023 14:03:35 -0700 Subject: [PATCH] Add repeatCount in superpmi.exe --- .../superpmi-shared/methodcontextreader.cpp | 27 ++++++++++++-- .../superpmi-shared/methodcontextreader.h | 14 +++++--- .../tools/superpmi/superpmi/commandline.cpp | 35 +++++++++++++++++++ .../tools/superpmi/superpmi/commandline.h | 1 + .../superpmi/superpmi/parallelsuperpmi.cpp | 5 +++ .../tools/superpmi/superpmi/superpmi.cpp | 6 +++- 6 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp index ef081077557565..bcae13d516a284 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp @@ -67,13 +67,15 @@ std::string MethodContextReader::CheckForPairedFile(const std::string& fileName, } MethodContextReader::MethodContextReader( - const char* inputFileName, const int* indexes, int indexCount, char* hash, int offset, int increment) + const char* inputFileName, const int* indexes, int indexCount, int repeatCount, char* hash, int offset, int increment) : fileHandle(INVALID_HANDLE_VALUE) , fileSize(0) , curMCIndex(0) , Indexes(indexes) , IndexCount(indexCount) , curIndexPos(0) + , RepeatCount(repeatCount) + , curRepeatIter(0) , Hash(hash) , curTOCIndex(0) , Offset(offset) @@ -130,6 +132,21 @@ MethodContextReader::~MethodContextReader() CleanExcludedMethods(); } +void MethodContextReader::Reset() +{ + this->curRepeatIter++; + + // resets for `-compile` + this->curIndexPos = 0; + // resets for `-stride` + this->curMCIndex = 0; + // resets for `-methodhash` + this->curTOCIndex = 0; + // resets for `mch files` + __int64 pos = 0; + SetFilePointerEx(this->fileHandle, *(PLARGE_INTEGER)&pos, (PLARGE_INTEGER)&pos, FILE_BEGIN); +} + bool MethodContextReader::AcquireLock() { DWORD res = WaitForSingleObject(this->mutex, INFINITE); @@ -411,13 +428,17 @@ double MethodContextReader::PercentComplete() if (this->hasIndex() && this->hasTOC()) { // Best estimate I can come up with... - return 100.0 * (double)this->curIndexPos / (double)this->IndexCount; + double completed = (this->curRepeatIter * this->IndexCount) + curIndexPos; + double total = this->RepeatCount * this->IndexCount; + return 100.0 * completed / total; } this->AcquireLock(); __int64 pos = 0; SetFilePointerEx(this->fileHandle, *(PLARGE_INTEGER)&pos, (PLARGE_INTEGER)&pos, FILE_CURRENT); this->ReleaseLock(); - return 100.0 * (double)pos / (double)this->fileSize; + double completed = (this->curRepeatIter * (double)this->fileSize) + pos; + double total = this->RepeatCount * (double)this->fileSize; + return 100.0 * completed / total; } // Binary search to get this method number from the index diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h index c43a2ab5a0c5cf..999a96c02942ba 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h @@ -68,6 +68,8 @@ class MethodContextReader const int* Indexes; int IndexCount; int curIndexPos; + int RepeatCount; + int curRepeatIter; // Method hash to process // If you have an index file, these things get processed @@ -124,12 +126,14 @@ class MethodContextReader public: MethodContextReader(const char* inputFileName, - const int* indexes = nullptr, - int indexCount = -1, - char* hash = nullptr, - int offset = -1, - int increment = -1); + const int* indexes = nullptr, + int indexCount = -1, + int repeatCount = -1, + char* hash = nullptr, + int offset = -1, + int increment = -1); ~MethodContextReader(); + void Reset(); // Read a method context buffer from the ContextCollection // (either a hive [single] or an index) diff --git a/src/coreclr/tools/superpmi/superpmi/commandline.cpp b/src/coreclr/tools/superpmi/superpmi/commandline.cpp index 8f9529a72812af..5fcc000922e880 100644 --- a/src/coreclr/tools/superpmi/superpmi/commandline.cpp +++ b/src/coreclr/tools/superpmi/superpmi/commandline.cpp @@ -117,6 +117,9 @@ void CommandLine::DumpHelp(const char* program) printf(" -skipCleanup\n"); printf(" Skip deletion of temporary files created by child SuperPMI processes with -parallel.\n"); printf("\n"); + printf(" -repeatCount \n"); + printf(" Number of times the compilation should repeat for given method contexts. Usually used when trying to measure JIT TP for specific set of methods. Default= 1.\n"); + printf("\n"); printf(" -target \n"); printf(" Used by the assembly differences calculator. This specifies the target\n"); printf(" architecture for cross-compilation. Currently allowed values: x64, x86, arm, arm64\n"); @@ -526,6 +529,38 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o) { o->skipCleanup = true; } + else if ((_stricmp(&argv[i][1], "repeatCount") == 0)) + { + if (++i < argc) + { + bool isValidCompileCount = true; + size_t nextlen = strlen(argv[i]); + for (size_t j = 0; j < nextlen; j++) + { + if (!isdigit(argv[i][j])) + { + isValidCompileCount = false; + break; + } + } + if (isValidCompileCount) + { + o->repeatCount = atoi(argv[i]); + + if (o->repeatCount < 1) + { + LogError("Invalid repeat count specified, workers count must be between 1 and INT_MAX."); + DumpHelp(argv[0]); + return false; + } + } + } + else + { + DumpHelp(argv[0]); + return false; + } + } else if ((_strnicmp(&argv[i][1], "stride", argLen) == 0)) { // "-stride" is an internal switch used by -parallel. Usage is: diff --git a/src/coreclr/tools/superpmi/superpmi/commandline.h b/src/coreclr/tools/superpmi/superpmi/commandline.h index 70f01fbf1018ce..6b1bdbd05b8dc1 100644 --- a/src/coreclr/tools/superpmi/superpmi/commandline.h +++ b/src/coreclr/tools/superpmi/superpmi/commandline.h @@ -34,6 +34,7 @@ class CommandLine int workerCount = -1; // Number of workers to use for /parallel mode. -1 (or 1) means don't use parallel mode. int indexCount = -1; // If indexCount is -1 and hash points to nullptr it means compile all. int failureLimit = -1; // Number of failures after which bail out the replay/asmdiffs. + int repeatCount = 1; // Number of times given methods should be compiled. int* indexes = nullptr; char* hash = nullptr; char* methodStatsTypes = nullptr; diff --git a/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp index f5b51fe05b753f..701b52ffe4049e 100644 --- a/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp @@ -592,6 +592,11 @@ int doParallelSuperPMI(CommandLine::Options& o) bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -v ewmin %s", spmiArgs); + if (o.repeatCount > 1) + { + bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -repeatCount %d", o.repeatCount); + } + SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index c99f54c9cfc913..f2d2ab05a6b508 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -288,7 +288,7 @@ int __cdecl main(int argc, char* argv[]) // The method context reader handles skipping any unrequested method contexts // Used in conjunction with an MCI file, it does a lot less work... MethodContextReader* reader = - new MethodContextReader(o.nameOfInputMethodContextFile, o.indexes, o.indexCount, o.hash, o.offset, o.increment); + new MethodContextReader(o.nameOfInputMethodContextFile, o.indexes, o.indexCount, o.repeatCount, o.hash, o.offset, o.increment); if (!reader->isValid()) { return (int)SpmiResult::GeneralFailure; @@ -327,6 +327,8 @@ int __cdecl main(int argc, char* argv[]) } } + for (int iter = 0; iter < o.repeatCount; iter++) + { while (true) { MethodContextBuffer mcb = reader->GetNextMethodContext(); @@ -709,6 +711,8 @@ int __cdecl main(int argc, char* argv[]) delete crl; delete mc; + } + reader->Reset(); } delete reader;