aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/lwtrace/perf.cpp
blob: 03b68586eaab53ed57f1aaafe0a12e0929a55377 (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
#include "perf.h"

#include "probes.h"

#include <util/system/datetime.h>
#include <util/system/hp_timer.h>

namespace NLWTrace {
    LWTRACE_USING(LWTRACE_INTERNAL_PROVIDER);

    TCpuTracker::TCpuTracker()
        : MinReportPeriod(NHPTimer::GetCyclesPerSecond())
    {
        ResetStats();
    }

    void TCpuTracker::Enter() {
        LastTs = GetCycleCount();
    }

    void TCpuTracker::Exit(const TProbe* probe) {
        ui64 exitTs = GetCycleCount();
        if (exitTs < LastTs) {
            return; // probably TSC was reset
        }
        ui64 cycles = exitTs - LastTs;
        LastTs = exitTs;

        AddStats(probe, cycles);
    }

    void TCpuTracker::AddStats(const TProbe* probe, ui64 cycles) {
        if (MaxCycles < cycles) {
            MaxProbe = probe;
            MaxCycles = cycles;
        }
        if (MinCycles > cycles) {
            MinCycles = cycles;
        }
        ProbeCycles += cycles;
        Count++;

        if (LastTs - LastReportTs > MinReportPeriod) {
            Report();
        }
    }

    void TCpuTracker::ResetStats() {
        MaxCycles = 0;
        MaxProbe = nullptr;
        MinCycles = ui64(-1);
        ProbeCycles = 0;
        Count = 0;
    }

    void TCpuTracker::Report() {
        if (!Reporting) {
            Reporting = true;
            ReportNotReentrant();
            Reporting = false;
        }
    }

    void TCpuTracker::ReportNotReentrant() {
        if (LastReportTs && Count > 0 && LastTs > LastReportTs) {
            ui64 reportPeriod = LastTs - LastReportTs;
            double share = double(ProbeCycles) / reportPeriod;
            double minMs = MilliSeconds(MinCycles);
            double maxMs = MilliSeconds(MaxCycles);
            double avgMs = MilliSeconds(ProbeCycles) / Count;
            LastReportTs = LastTs;
            ResetStats();
            LWPROBE(PerfReport, share, minMs, maxMs, avgMs);
        } else {
            LastReportTs = LastTs;
            ResetStats();
        }
    }

    double TCpuTracker::MilliSeconds(ui64 cycles) {
        return NHPTimer::GetSeconds(cycles) * 1000.0;
    }

}