File: perf.cc

package info (click to toggle)
mold 2.37.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 43,640 kB
  • sloc: ansic: 190,908; cpp: 153,224; asm: 29,233; sh: 13,504; python: 4,247; makefile: 3,322; ada: 1,681; pascal: 1,139; xml: 278; objc: 176; javascript: 37
file content (120 lines) | stat: -rw-r--r-- 2,861 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "common.h"

#include <functional>
#include <iomanip>
#include <ios>
#include <tbb/concurrent_vector.h>

#ifndef _WIN32
#include <sys/resource.h>
#include <sys/time.h>
#endif

namespace mold {

i64 Counter::get_value() {
  return values.combine(std::plus());
}

void Counter::print() {
  sort(instances, [](Counter *a, Counter *b) {
    return a->get_value() > b->get_value();
  });

  for (Counter *c : instances)
    std::cout << std::setw(20) << std::right << c->name
              << "=" << c->get_value() << "\n";
}

static i64 now_nsec() {
  return (i64)std::chrono::steady_clock::now().time_since_epoch().count();
}

static std::pair<i64, i64> get_usage() {
#ifdef _WIN32
  auto to_nsec = [](FILETIME t) -> i64 {
    return (((u64)t.dwHighDateTime << 32) + (u64)t.dwLowDateTime) * 100;
  };

  FILETIME creation, exit, kernel, user;
  GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user);
  return {to_nsec(user), to_nsec(kernel)};
#else
  auto to_nsec = [](struct timeval t) -> i64 {
    return (i64)t.tv_sec * 1'000'000'000 + t.tv_usec * 1'000;
  };

  struct rusage ru;
  getrusage(RUSAGE_SELF, &ru);
  return {to_nsec(ru.ru_utime), to_nsec(ru.ru_stime)};
#endif
}

TimerRecord::TimerRecord(std::string name, TimerRecord *parent)
  : name(name), parent(parent) {
  start = now_nsec();
  std::tie(user, sys) = get_usage();
  if (parent)
    parent->children.push_back(this);
}

void TimerRecord::stop() {
  if (stopped)
    return;
  stopped = true;

  i64 user2;
  i64 sys2;
  std::tie(user2, sys2) = get_usage();

  end = now_nsec();
  user = user2 - user;
  sys = sys2 - sys;
}

static void print_rec(TimerRecord &rec, i64 indent) {
  printf(" % 8.3f % 8.3f % 8.3f  %s%s\n",
         ((double)rec.user / 1'000'000'000),
         ((double)rec.sys / 1'000'000'000),
         (((double)rec.end - rec.start) / 1'000'000'000),
         std::string(indent * 2, ' ').c_str(),
         rec.name.c_str());

  sort(rec.children, [](TimerRecord *a, TimerRecord *b) {
    return a->start < b->start;
  });

  for (TimerRecord *child : rec.children)
    print_rec(*child, indent + 1);
}

void print_timer_records(
    tbb::concurrent_vector<std::unique_ptr<TimerRecord>> &records) {
  for (i64 i = records.size() - 1; i >= 0; i--)
    records[i]->stop();

  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;
      }
    }
  }

  std::cout << "     User   System     Real  Name\n";

  for (std::unique_ptr<TimerRecord> &rec : records)
    if (!rec->parent)
      print_rec(*rec, 0);

  std::cout << std::flush;
}

} // namespace mold