aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/perfprofiler/perftimelinemodel.h
blob: 26138369b18b12a9317b09d1c66b9e0437b20729 (plain)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0

#pragma once

#include "perfprofilertracemanager.h"
#include "perftimelinemodelmanager.h"
#include "perfresourcecounter.h"

#include <tracing/timelinemodel.h>

#include <QStack>

namespace PerfProfiler {
namespace Internal {

class PerfTimelineModel : public Timeline::TimelineModel
{
    Q_OBJECT
public:

    struct LocationStats {
        LocationStats() : numSamples(0), numUniqueSamples(0), stackPosition(0) {}
        int numSamples;
        int numUniqueSamples;
        int stackPosition;
    };

    enum SpecialRows {
        SpaceRow = 0,
        SamplesRow = 1,
        MaximumSpecialRow = 2
    };

    PerfTimelineModel(quint32 pid, quint32 tid, qint64 startTime, qint64 endTime,
                      PerfTimelineModelManager *parent);

    QRgb color(int index) const override;
    QVariantList labels() const override;
    QVariantMap details(int index) const override;
    QVariantMap location(int index) const override;
    int typeId(int index) const override;
    bool handlesTypeId(int typeId) const override;

    int expandedRow(int index) const override;
    int collapsedRow(int index) const override;
    float relativeHeight(int index) const override;

    void loadEvent(const PerfEvent &event, int numConcurrentThreads);
    void finalize();

    void clear() override;

    quint32 pid() const { return m_pid; }
    quint32 tid() const { return m_tid; }

    qint64 threadStartTimestamp() const { return m_threadStartTimestamp + 1; }
    qint64 threadEndTimestamp() const { return m_threadEndTimestamp - 1; }

    void setSamplingFrequency(qint64 samplingFrequency) { m_samplingFrequency = samplingFrequency; }

    bool isResourceTracePoint(int index) const;
    float resourceUsage(int index) const;
    bool isSample(int index) const
    {
        return selectionId(index) <= PerfEvent::LastSpecialTypeId;
    }

    int numAttributes(int index) const;
    qint32 attributeId(int index, int i) const;
    quint64 attributeValue(int index, int i) const;

    QHash<qint32, QVariant> extraData(int index) const { return m_extraData.value(index); }

    qint64 rowMinValue(int rowNumber) const override;
    qint64 rowMaxValue(int rowNumber) const override;
    QList<const Timeline::TimelineRenderPass *> supportedRenderPasses() const override;

    void addLostEvent(qint64 timestamp, int numConcurrentThreads);

private:
    struct StackFrame {
        int numSamples = 1;
        int numExpectedParallelSamples = 1;
        int displayRowCollapsed = MaximumSpecialRow;
        int displayRowExpanded = MaximumSpecialRow;

        quint64 attributeValue = 0;
        qint64 resourcePeak = 0;
        qint64 resourceDelta = 0;
        int resourceGuesses = 0;
        int numAttributes = 0;

        static StackFrame sampleFrame()
        {
            StackFrame sample = StackFrame();
            sample.displayRowCollapsed = sample.displayRowExpanded = SamplesRow;
            return sample;
        }

        static StackFrame contentFrame(bool guessed, int numConcurrentThreads, int level,
                                       qint64 currentTotal, qint64 delta, int guesses)
        {
            StackFrame stackFrame = StackFrame();
            stackFrame.numSamples = guessed ? -1 : 1;
            stackFrame.numExpectedParallelSamples = numConcurrentThreads;
            stackFrame.displayRowCollapsed = level + MaximumSpecialRow;
            stackFrame.resourcePeak = currentTotal;
            stackFrame.resourceDelta = delta;
            stackFrame.resourceGuesses = guesses;
            return stackFrame;
        }
    };

    QVector<int> m_currentStack;

    qint64 m_lastTimestamp;
    qint64 m_threadStartTimestamp;
    qint64 m_threadEndTimestamp;

    PerfResourceCounter<> m_resourceBlocks;

    QVector<int> m_locationOrder;
    QHash<int, LocationStats> m_locationStats;

    quint32 m_pid;
    quint32 m_tid;
    qint64 m_samplingFrequency;

    QVector<StackFrame> m_data;
    QHash<int, QHash<qint32, QVariant>> m_extraData;
    QHash<int, QVector<QPair<qint32, quint64>>> m_attributeValues;

    void computeExpandedLevels();
    const PerfProfilerTraceManager *traceManager() const;

    const LocationStats &locationStats(int selectionId) const;

    void updateTraceData(const PerfEvent &event);
    void updateFrames(const PerfEvent &event, int numConcurrentThreads, qint64 resourceDelta,
                      int guesses);
    void addSample(const PerfEvent &event, qint64 resourceDelta,
                   int guesses);
};

} // namespace Internal
} // namespace PerfProfiler