@@ -210,13 +210,15 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
210
210
quint64 maxRuntime = 0 ;
211
211
quint64 offCpuTime = 0 ;
212
212
quint64 numEvents = 0 ;
213
- for (const auto tid : process.threads ) {
214
- const auto thread = m_data.findThread (process.pid , tid);
215
- Q_ASSERT (thread);
216
- runtime += thread->time .delta ();
217
- maxRuntime = std::max (thread->time .delta (), maxRuntime);
218
- offCpuTime += thread->offCpuTime ;
219
- numEvents += thread->events .size ();
213
+ for (const auto tidCostId : process.threads ) {
214
+ for (const auto & thread : m_data.threads ) {
215
+ if (thread.tid == tidCostId.tid ) {
216
+ runtime += thread.time .delta ();
217
+ maxRuntime = std::max (thread.time .delta (), maxRuntime);
218
+ offCpuTime += thread.offCpuTime ;
219
+ numEvents += thread.events .size ();
220
+ }
221
+ }
220
222
}
221
223
222
224
const auto totalRuntime = m_time.delta ();
@@ -249,8 +251,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
249
251
cpu = &m_data.cpus [index.row ()];
250
252
} else if (tag == Tag::Threads) {
251
253
const auto process = m_processes.value (tagData (index.internalId ()));
252
- const auto tid = process.threads .value (index.row ());
253
- thread = m_data.findThread (process.pid , tid);
254
+ const auto tid = process.threads [index.row ()].tid ;
255
+ const auto costId = process.threads [index.row ()].costId ;
256
+ thread = m_data.findThread (process.pid , tid, costId);
254
257
Q_ASSERT (thread);
255
258
} else if (tag == Tag::Tracepoints) {
256
259
tracepoint = &m_data.tracepoints [index.row ()];
@@ -521,36 +524,68 @@ void EventModel::setData(const Data::EventResults& data)
521
524
if (data.threads .isEmpty ()) {
522
525
m_time = {};
523
526
} else {
527
+ const auto numCostTypes = m_data.totalCosts .size ();
524
528
m_time = data.threads .first ().time ;
529
+ m_data.threads .clear ();
525
530
for (const auto & thread : data.threads ) {
526
531
m_time.start = std::min (thread.time .start , m_time.start );
527
532
m_time.end = std::max (thread.time .end , m_time.end );
528
533
m_totalOffCpuTime += thread.offCpuTime ;
529
534
m_totalOnCpuTime += thread.time .delta () - thread.offCpuTime ;
530
535
m_totalEvents += thread.events .size ();
531
536
auto it = std::lower_bound (m_processes.begin (), m_processes.end (), thread.pid , orderProcessByPid);
532
- if (it == m_processes.end () || it->pid != thread.pid ) {
533
- m_processes.insert (it, {thread.pid , {thread.tid }, thread.name });
534
- } else {
535
- it->threads .append (thread.tid );
536
- // prefer process name, if we encountered a thread first
537
- if (thread.pid == thread.tid )
538
- it->name = thread.name ;
539
- }
540
537
541
- for (const auto & event : thread.events ) {
542
- if (event.type != 0 ) {
543
- // TODO: support multiple cost types somehow
544
- continue ;
538
+ for (int eventType = 0 ; eventType < numCostTypes; eventType++) {
539
+ Data::ThreadEvents event {
540
+ thread.pid , thread.tid , thread.time , {}, thread.name , thread.lastSwitchTime ,
541
+ thread.offCpuTime , thread.state };
542
+
543
+ std::copy_if (thread.events .cbegin (), thread.events .cend (), std::back_inserter (event.events ),
544
+ [eventType](const Data::Event& event) { return eventType == event.type ; });
545
+
546
+ if (!event.events .isEmpty ()) {
547
+ m_data.threads .push_back (event);
548
+ if (it == m_processes.end () || it->pid != thread.pid ) {
549
+ it = m_processes.insert (it, {thread.pid , {{thread.tid , eventType}}, thread.name });
550
+ } else {
551
+ it->threads .append ({thread.tid , eventType});
552
+ // prefer process name, if we encountered a thread first
553
+ if (thread.pid == thread.tid )
554
+ it->name = thread.name ;
555
+ }
545
556
}
546
- m_maxCost = std::max (event.cost , m_maxCost);
557
+ }
558
+
559
+ // TODO: support multiple cost types somehow
560
+ if (!thread.events .isEmpty () && thread.events [0 ].type == 0 ) {
561
+ auto maxElement = std::max_element (thread.events .cbegin (), thread.events .cend (),
562
+ [](const auto & a, const auto & b) { return a.cost < b.cost ; });
563
+ m_maxCost = std::max (maxElement->cost , m_maxCost);
547
564
}
548
565
}
549
566
550
567
// don't show timeline for CPU cores that did not receive any events
551
568
auto it = std::remove_if (m_data.cpus .begin (), m_data.cpus .end (),
552
569
[](const Data::CpuEvents& cpuEvents) { return cpuEvents.events .isEmpty (); });
553
570
m_data.cpus .erase (it, m_data.cpus .end ());
571
+
572
+ // split events to that each CpuEvents entry contains only one event type
573
+ QVector<Data::CpuEvents> cpuEventsExpanded;
574
+
575
+ for (const auto & cpu : std::as_const (m_data.cpus )) {
576
+ for (int eventType = 0 ; eventType < numCostTypes; eventType++) {
577
+ Data::CpuEvents event;
578
+ event.cpuId = cpu.cpuId ;
579
+ std::copy_if (cpu.events .cbegin (), cpu.events .cend (), std::back_inserter (event.events ),
580
+ [eventType](const Data::Event& event) { return eventType == event.type ; });
581
+
582
+ if (!event.events .isEmpty ()) {
583
+ cpuEventsExpanded.append (event);
584
+ }
585
+ }
586
+ }
587
+ // Keep the data somehow so that we can show all events if no source is selected
588
+ m_data.cpus = cpuEventsExpanded;
554
589
}
555
590
556
591
endResetModel ();
0 commit comments