aboutsummaryrefslogtreecommitdiffstats
path: root/util/datetime/cputimer.h
blob: b24d6fae8e411d937e5cf872d28a793c8adb9401 (plain) (blame)
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
121
122
123
124
125
126
127
128
#pragma once

#include "base.h"

#include <util/system/rusage.h>
#include <util/generic/string.h>
#include <util/stream/str.h>

class TTimer {
private:
    TInstant Start_;
    TStringStream Message_;

public:
    TTimer(const TStringBuf message = TStringBuf(" took: "));
    ~TTimer();
};

class TSimpleTimer {
    TInstant T;

public:
    TSimpleTimer() {
        Reset();
    }
    TDuration Get() const {
        return TInstant::Now() - T;
    }
    void Reset() {
        T = TInstant::Now();
    }
};

class TProfileTimer {
    TDuration T;

public:
    TProfileTimer() {
        Reset();
    }
    TDuration Get() const {
        return TRusage::Get().Utime - T;
    }
    TDuration Step() {
        TRusage r;
        r.Fill();
        TDuration d = r.Utime - T;
        T = r.Utime;
        return d;
    }
    void Reset() {
        T = TRusage::Get().Utime;
    }
};

/// Return cached processor cycle count per second. Method takes 1 second at first invocation.
/// Note, on older systems cycle rate may change during program lifetime,
/// so returned value may be incorrect. Modern Intel and AMD processors keep constant TSC rate.
ui64 GetCyclesPerMillisecond();
void SetCyclesPerSecond(ui64 cycles);

TDuration CyclesToDuration(ui64 cycles);
ui64 DurationToCycles(TDuration duration);

// NBS-3400 - CyclesToDuration and DurationToCycles may overflow for long running events
TDuration CyclesToDurationSafe(ui64 cycles);
ui64 DurationToCyclesSafe(TDuration duration);

class TPrecisionTimer {
private:
    ui64 Start = 0;

public:
    TPrecisionTimer();

    ui64 GetCycleCount() const;
};

TString FormatCycles(ui64 cycles);

class TFormattedPrecisionTimer {
private:
    ui64 Start;
    const char* Message;
    IOutputStream* Out;

public:
    TFormattedPrecisionTimer(const char* message = "took ", IOutputStream* out = &Cout);
    ~TFormattedPrecisionTimer();
};

class TFuncTimer {
public:
    TFuncTimer(const char* func);
    ~TFuncTimer();

private:
    const TInstant Start_;
    const char* Func_;
};

class TFakeTimer {
public:
    inline TFakeTimer(const char* = nullptr) noexcept {
    }
};

#if defined(WITH_DEBUG)
    #define TDebugTimer TFuncTimer
#else
    #define TDebugTimer TFakeTimer
#endif

class TTimeLogger {
private:
    TString Message;
    bool Verbose;
    bool OK;
    time_t Begin;
    ui64 BeginCycles;

public:
    TTimeLogger(const TString& message, bool verbose = true);
    ~TTimeLogger();

    void SetOK();
    double ElapsedTime() const;
};