|
83 | 83 | #include <limits>
|
84 | 84 | #include <tuple>
|
85 | 85 |
|
| 86 | +#ifdef PROFILE_OPTIMIZER_STEPS |
| 87 | +#include <chrono> |
| 88 | +#include <fmt/format.h> |
| 89 | +#endif |
| 90 | + |
86 | 91 | using namespace std;
|
87 | 92 | using namespace solidity;
|
88 | 93 | 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 | + |
89 | 135 |
|
90 | 136 | void OptimiserSuite::run(
|
91 | 137 | Dialect const& _dialect,
|
@@ -178,13 +224,16 @@ void OptimiserSuite::run(
|
178 | 224 | NameSimplifier::run(suite.m_context, ast);
|
179 | 225 | VarNameCleaner::run(suite.m_context, ast);
|
180 | 226 |
|
| 227 | +#ifdef PROFILE_OPTIMIZER_STEPS |
| 228 | + outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); |
| 229 | +#endif |
| 230 | + |
181 | 231 | *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object);
|
182 | 232 | }
|
183 | 233 |
|
184 | 234 | namespace
|
185 | 235 | {
|
186 | 236 |
|
187 |
| - |
188 | 237 | template <class... Step>
|
189 | 238 | map<string, unique_ptr<OptimiserStep>> optimiserStepCollection()
|
190 | 239 | {
|
@@ -445,7 +494,14 @@ void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
|
445 | 494 | {
|
446 | 495 | if (m_debug == Debug::PrintStep)
|
447 | 496 | cout << "Running " << step << endl;
|
| 497 | +#ifdef PROFILE_OPTIMIZER_STEPS |
| 498 | + steady_clock::time_point startTime = steady_clock::now(); |
| 499 | +#endif |
448 | 500 | 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 |
449 | 505 | if (m_debug == Debug::PrintChanges)
|
450 | 506 | {
|
451 | 507 | // TODO should add switch to also compare variable names!
|
|
0 commit comments