aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/perfprofiler/perftimelinemodelmanager.cpp
blob: cd5e1c581f2d3588e8c361bad9ca8c6455e08dfd (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
// 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

#include "perftimelinemodel.h"
#include "perftimelinemodelmanager.h"

#include <utils/qtcassert.h>

namespace PerfProfiler {
namespace Internal {

PerfTimelineModelManager::PerfTimelineModelManager(PerfProfilerTraceManager *traceManager) :
    Timeline::TimelineModelAggregator(traceManager), m_traceManager(traceManager)
{
    traceManager->registerFeatures(PerfEventType::allFeatures(),
                                   std::bind(&PerfTimelineModelManager::loadEvent, this,
                                             std::placeholders::_1, std::placeholders::_2),
                                   std::bind(&PerfTimelineModelManager::initialize, this),
                                   std::bind(&PerfTimelineModelManager::finalize, this),
                                   std::bind(&PerfTimelineModelManager::clear, this));
}

PerfTimelineModelManager::~PerfTimelineModelManager()
{
    clear();
}

static QString displayNameForThread(const PerfProfilerTraceManager::Thread &thread,
                                    PerfProfilerTraceManager *manager)
{
    return QString::fromLatin1("%1 (%2)")
            .arg(QString::fromUtf8(manager->string(thread.name)))
            .arg(thread.tid);
}

void PerfTimelineModelManager::initialize()
{
    for (const PerfProfilerTraceManager::Thread &thread : m_traceManager->threads()) {
        if (thread.enabled) {
            m_unfinished.insert(thread.tid, new PerfTimelineModel(
                                    thread.pid, thread.tid, thread.firstEvent, thread.lastEvent,
                                    this));
        }
    }
}

void PerfTimelineModelManager::finalize()
{
    QVector<PerfTimelineModel *> finished;
    QHash<quint32, PerfProfilerTraceManager::Thread> threads = m_traceManager->threads();
    for (auto it = m_unfinished.begin(), end = m_unfinished.end(); it != end; ++it) {
        PerfTimelineModel *model = *it;

        const PerfProfilerTraceManager::Thread &thread = m_traceManager->thread(model->tid());
        if (thread.enabled) {
            model->setDisplayName(displayNameForThread(thread, m_traceManager));
            model->finalize();
            finished.append(model);
        } else {
            delete model;
        }
    }
    m_unfinished.clear();

    const qint64 frequency = m_traceManager->samplingFrequency();
    for (PerfTimelineModel *model : qAsConst(finished)) {
        model->setSamplingFrequency(frequency);
        threads.remove(model->tid());
    }

    for (const PerfProfilerTraceManager::Thread &remaining : threads) {
        if (!remaining.enabled)
            continue;
        PerfTimelineModel *model = new PerfTimelineModel(
                    remaining.pid, remaining.tid, remaining.firstEvent, remaining.lastEvent, this);
        model->setDisplayName(displayNameForThread(remaining, m_traceManager));
        model->finalize();
        model->setSamplingFrequency(frequency);
        finished.append(model);
    }

    std::sort(finished.begin(), finished.end(), [](PerfTimelineModel *a, PerfTimelineModel *b) {
        return a->tid() < b->tid();
    });

    QVariantList modelsToAdd;
    for (PerfTimelineModel *model : qAsConst(finished))
        modelsToAdd.append(QVariant::fromValue(model));
    setModels(modelsToAdd);
}

void PerfTimelineModelManager::loadEvent(const PerfEvent &event, const PerfEventType &type)
{
    Q_UNUSED(type)
    const int parallel = m_traceManager->threads().size();
    auto i = m_unfinished.find(event.tid());
    if (i == m_unfinished.end()) {
        i = m_unfinished.insert(event.tid(), new PerfTimelineModel(
                                    event.pid(), event.tid(), event.timestamp(), event.timestamp(),
                                    this));
    }
    (*i)->loadEvent(event, parallel);
}

void PerfTimelineModelManager::clear()
{
    QVariantList perfModels = models();
    Timeline::TimelineModelAggregator::clear();
    for (QVariant &var : perfModels)
        delete qvariant_cast<PerfTimelineModel *>(var);
    qDeleteAll(m_unfinished);
    m_unfinished.clear();
    m_resourceContainers.clear();
}

} // namespace Internal
} // namespace PerfProfiler