Skip to content

Commit be8ecb1

Browse files
authored
Merge pull request #13703 from ethereum/performance_metrics
Code to output performance metrics for optimizer steps.
2 parents 3109ce2 + 5950ec3 commit be8ecb1

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms"
3636
option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libstdc++ on supported platforms" OFF)
3737
option(STRICT_Z3_VERSION "Use the latest version of Z3" ON)
3838
option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON)
39+
option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF)
3940

4041
# Setup cccache.
4142
include(EthCcache)
@@ -52,6 +53,11 @@ find_package(Threads)
5253
if(NOT PEDANTIC)
5354
message(WARNING "-- Pedantic build flags turned off. Warnings will not make compilation fail. This is NOT recommended in development builds.")
5455
endif()
56+
57+
if (PROFILE_OPTIMIZER_STEPS)
58+
add_definitions(-DPROFILE_OPTIMIZER_STEPS)
59+
endif()
60+
5561
# Figure out what compiler and system are we using
5662
include(EthCompilerSettings)
5763

libyul/optimiser/Suite.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,55 @@
8383
#include <limits>
8484
#include <tuple>
8585

86+
#ifdef PROFILE_OPTIMIZER_STEPS
87+
#include <chrono>
88+
#include <fmt/format.h>
89+
#endif
90+
8691
using namespace std;
8792
using namespace solidity;
8893
using namespace solidity::yul;
94+
#ifdef PROFILE_OPTIMIZER_STEPS
95+
using namespace std::chrono;
96+
#endif
97+
98+
namespace
99+
{
100+
101+
#ifdef PROFILE_OPTIMIZER_STEPS
102+
void outputPerformanceMetrics(map<string, int64_t> const& _metrics)
103+
{
104+
vector<pair<string, int64_t>> durations(_metrics.begin(), _metrics.end());
105+
sort(
106+
durations.begin(),
107+
durations.end(),
108+
[](pair<string, int64_t> const& _lhs, pair<string, int64_t> const& _rhs) -> bool
109+
{
110+
return _lhs.second < _rhs.second;
111+
}
112+
);
113+
114+
int64_t totalDurationInMicroseconds = 0;
115+
for (auto&& [step, durationInMicroseconds]: durations)
116+
totalDurationInMicroseconds += durationInMicroseconds;
117+
118+
cerr << "Performance metrics of optimizer steps" << endl;
119+
cerr << "======================================" << endl;
120+
constexpr double microsecondsInSecond = 1000000;
121+
for (auto&& [step, durationInMicroseconds]: durations)
122+
{
123+
double percentage = 100.0 * static_cast<double>(durationInMicroseconds) / static_cast<double>(totalDurationInMicroseconds);
124+
double sec = static_cast<double>(durationInMicroseconds) / microsecondsInSecond;
125+
cerr << fmt::format("{:>7.3f}% ({} s): {}", percentage, sec, step) << endl;
126+
}
127+
double totalDurationInSeconds = static_cast<double>(totalDurationInMicroseconds) / microsecondsInSecond;
128+
cerr << "--------------------------------------" << endl;
129+
cerr << fmt::format("{:>7}% ({:.3f} s)", 100, totalDurationInSeconds) << endl;
130+
}
131+
#endif
132+
133+
}
134+
89135

90136
void OptimiserSuite::run(
91137
Dialect const& _dialect,
@@ -178,13 +224,16 @@ void OptimiserSuite::run(
178224
NameSimplifier::run(suite.m_context, ast);
179225
VarNameCleaner::run(suite.m_context, ast);
180226

227+
#ifdef PROFILE_OPTIMIZER_STEPS
228+
outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds);
229+
#endif
230+
181231
*_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object);
182232
}
183233

184234
namespace
185235
{
186236

187-
188237
template <class... Step>
189238
map<string, unique_ptr<OptimiserStep>> optimiserStepCollection()
190239
{
@@ -445,7 +494,14 @@ void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
445494
{
446495
if (m_debug == Debug::PrintStep)
447496
cout << "Running " << step << endl;
497+
#ifdef PROFILE_OPTIMIZER_STEPS
498+
steady_clock::time_point startTime = steady_clock::now();
499+
#endif
448500
allSteps().at(step)->run(m_context, _ast);
501+
#ifdef PROFILE_OPTIMIZER_STEPS
502+
steady_clock::time_point endTime = steady_clock::now();
503+
m_durationPerStepInMicroseconds[step] += duration_cast<microseconds>(endTime - startTime).count();
504+
#endif
449505
if (m_debug == Debug::PrintChanges)
450506
{
451507
// TODO should add switch to also compare variable names!

libyul/optimiser/Suite.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class OptimiserSuite
8787
private:
8888
OptimiserStepContext& m_context;
8989
Debug m_debug;
90+
#ifdef PROFILE_OPTIMIZER_STEPS
91+
std::map<std::string, int64_t> m_durationPerStepInMicroseconds;
92+
#endif
9093
};
9194

9295
}

0 commit comments

Comments
 (0)