2023-01-16 10:26:52 +03:00
|
|
|
#include "common.h"
|
2020-11-03 11:26:42 +03:00
|
|
|
|
2021-01-25 09:23:04 +03:00
|
|
|
#include <functional>
|
2020-12-10 16:32:47 +03:00
|
|
|
#include <iomanip>
|
|
|
|
#include <ios>
|
2022-07-13 22:42:49 +03:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
2020-12-11 10:51:20 +03:00
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/time.h>
|
2022-07-13 22:42:49 +03:00
|
|
|
#endif
|
2020-12-10 16:32:47 +03:00
|
|
|
|
2021-09-27 12:14:56 +03:00
|
|
|
namespace mold {
|
2021-09-02 12:19:43 +03:00
|
|
|
|
2021-01-25 09:23:04 +03:00
|
|
|
i64 Counter::get_value() {
|
|
|
|
return values.combine(std::plus());
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:26:42 +03:00
|
|
|
void Counter::print() {
|
2021-01-25 09:23:04 +03:00
|
|
|
sort(instances, [](Counter *a, Counter *b) {
|
|
|
|
return a->get_value() > b->get_value();
|
|
|
|
});
|
2020-11-03 11:26:42 +03:00
|
|
|
|
2021-01-25 09:23:04 +03:00
|
|
|
for (Counter *c : instances)
|
|
|
|
std::cout << std::setw(20) << std::right << c->name
|
|
|
|
<< "=" << c->get_value() << "\n";
|
2020-11-03 11:26:42 +03:00
|
|
|
}
|
2020-12-11 10:51:20 +03:00
|
|
|
|
2021-01-24 07:26:03 +03:00
|
|
|
static i64 now_nsec() {
|
2022-07-16 19:38:34 +03:00
|
|
|
return (i64)std::chrono::steady_clock::now().time_since_epoch().count();
|
2020-12-11 10:51:20 +03:00
|
|
|
}
|
|
|
|
|
2022-08-12 11:44:51 +03:00
|
|
|
static std::pair<i64, i64> get_usage() {
|
2022-07-16 19:38:34 +03:00
|
|
|
#ifdef _WIN32
|
2022-08-12 11:44:51 +03:00
|
|
|
auto to_nsec = [](FILETIME t) -> i64 {
|
2024-02-20 19:26:25 +03:00
|
|
|
return (((u64)t.dwHighDateTime << 32) + (u64)t.dwLowDateTime) * 100;
|
2022-08-12 11:44:51 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
FILETIME creation, exit, kernel, user;
|
|
|
|
GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user);
|
|
|
|
return {to_nsec(user), to_nsec(kernel)};
|
2022-07-16 19:38:34 +03:00
|
|
|
#else
|
2022-08-12 11:44:51 +03:00
|
|
|
auto to_nsec = [](struct timeval t) -> i64 {
|
2023-01-23 16:45:06 +03:00
|
|
|
return (i64)t.tv_sec * 1'000'000'000 + t.tv_usec * 1'000;
|
2022-08-12 11:44:51 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct rusage ru;
|
|
|
|
getrusage(RUSAGE_SELF, &ru);
|
|
|
|
return {to_nsec(ru.ru_utime), to_nsec(ru.ru_stime)};
|
2022-07-16 19:38:34 +03:00
|
|
|
#endif
|
2022-08-12 11:44:51 +03:00
|
|
|
}
|
2020-12-11 10:51:20 +03:00
|
|
|
|
2021-04-07 09:38:31 +03:00
|
|
|
TimerRecord::TimerRecord(std::string name, TimerRecord *parent)
|
|
|
|
: name(name), parent(parent) {
|
2020-12-11 10:51:20 +03:00
|
|
|
start = now_nsec();
|
2022-08-12 11:44:51 +03:00
|
|
|
std::tie(user, sys) = get_usage();
|
2021-04-07 09:38:31 +03:00
|
|
|
if (parent)
|
|
|
|
parent->children.push_back(this);
|
2020-12-11 10:51:20 +03:00
|
|
|
}
|
|
|
|
|
2021-01-09 12:15:09 +03:00
|
|
|
void TimerRecord::stop() {
|
2020-12-11 10:51:20 +03:00
|
|
|
if (stopped)
|
|
|
|
return;
|
|
|
|
stopped = true;
|
|
|
|
|
2022-08-12 11:44:51 +03:00
|
|
|
i64 user2;
|
|
|
|
i64 sys2;
|
|
|
|
std::tie(user2, sys2) = get_usage();
|
2020-12-11 10:51:20 +03:00
|
|
|
|
|
|
|
end = now_nsec();
|
2022-08-12 11:44:51 +03:00
|
|
|
user = user2 - user;
|
|
|
|
sys = sys2 - sys;
|
2020-12-11 10:51:20 +03:00
|
|
|
}
|
|
|
|
|
2021-04-04 12:46:43 +03:00
|
|
|
static void print_rec(TimerRecord &rec, i64 indent) {
|
|
|
|
printf(" % 8.3f % 8.3f % 8.3f %s%s\n",
|
2023-01-23 16:45:06 +03:00
|
|
|
((double)rec.user / 1'000'000'000),
|
|
|
|
((double)rec.sys / 1'000'000'000),
|
|
|
|
(((double)rec.end - rec.start) / 1'000'000'000),
|
2021-04-04 12:46:43 +03:00
|
|
|
std::string(indent * 2, ' ').c_str(),
|
|
|
|
rec.name.c_str());
|
|
|
|
|
2021-04-07 09:38:31 +03:00
|
|
|
sort(rec.children, [](TimerRecord *a, TimerRecord *b) {
|
|
|
|
return a->start < b->start;
|
|
|
|
});
|
2021-04-04 12:46:43 +03:00
|
|
|
|
|
|
|
for (TimerRecord *child : rec.children)
|
|
|
|
print_rec(*child, indent + 1);
|
|
|
|
}
|
|
|
|
|
2021-09-27 12:14:56 +03:00
|
|
|
void print_timer_records(
|
|
|
|
tbb::concurrent_vector<std::unique_ptr<TimerRecord>> &records) {
|
2021-01-24 06:01:43 +03:00
|
|
|
for (i64 i = records.size() - 1; i >= 0; i--)
|
2021-01-09 12:15:09 +03:00
|
|
|
records[i]->stop();
|
2020-12-11 10:51:20 +03:00
|
|
|
|
2021-04-04 12:46:43 +03:00
|
|
|
for (i64 i = 0; i < records.size(); i++) {
|
|
|
|
TimerRecord &inner = *records[i];
|
|
|
|
if (inner.parent)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i64 j = i - 1; j >= 0; j--) {
|
|
|
|
TimerRecord &outer = *records[j];
|
|
|
|
if (outer.start <= inner.start && inner.end <= outer.end) {
|
|
|
|
inner.parent = &outer;
|
|
|
|
outer.children.push_back(&inner);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-11 10:51:20 +03:00
|
|
|
|
|
|
|
std::cout << " User System Real Name\n";
|
|
|
|
|
2021-04-07 09:38:31 +03:00
|
|
|
for (std::unique_ptr<TimerRecord> &rec : records)
|
2021-04-04 12:46:43 +03:00
|
|
|
if (!rec->parent)
|
|
|
|
print_rec(*rec, 0);
|
2020-12-11 10:52:19 +03:00
|
|
|
|
2020-12-11 10:51:20 +03:00
|
|
|
std::cout << std::flush;
|
|
|
|
}
|
2021-04-07 09:38:31 +03:00
|
|
|
|
2021-09-27 12:14:56 +03:00
|
|
|
} // namespace mold
|