Show detailed CPU load information in a tool-tip (#5970)

* Profiler rework

* Workaround for GCC bug

* Rollback QFile removal

* Use enum instead of a plain index to describe detailed stats

* Use the GCC workaround code for all compilers to avoid redundancy

* Update and fix comments

* Implement suggestions from review

* Split AudioEngine::renderNextBuffer() into separate functions, fix old formatting

* Remove QFile include

* Revert formatting changes

* Apply suggestion from review (remove unnecessary template parameter)

* Revert more formatting changes

* Convert DetailType to enum class

* DetailType enum class improvements suggested in review

* Use std::atomic for m_detailLoad

* RAII-style profiler probes

* Apply suggestions from code review

Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

* Fix namespace comment

* Improve CPU load widget precision and use floats for load computations

* Atomic m_cpuLoad

* Add custom step size support for CPULoadWidget

* Apply suggestions from review (convert the profiler probe into a nested class, other small changes)

* Do not limit stored load averages to 100%

---------

Co-authored-by: sakertooth <sakertooth@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
This commit is contained in:
Martin Pavelek
2023-09-05 01:33:42 +02:00
committed by GitHub
parent fa05ce20b8
commit de062d6c54
8 changed files with 140 additions and 23 deletions

View File

@@ -275,6 +275,11 @@ public:
return m_profiler.cpuLoad();
}
int detailLoad(const AudioEngineProfiler::DetailType type) const
{
return m_profiler.detailLoad(type);
}
const qualitySettings & currentQualitySettings() const
{
return m_qualitySettings;
@@ -401,6 +406,10 @@ private:
AudioDevice * tryAudioDevices();
MidiClient * tryMidiClients();
void renderStageNoteSetup();
void renderStageInstruments();
void renderStageEffects();
void renderStageMix();
const surroundSampleFrame * renderNextBuffer();

View File

@@ -25,6 +25,8 @@
#ifndef LMMS_AUDIO_ENGINE_PROFILER_H
#define LMMS_AUDIO_ENGINE_PROFILER_H
#include <array>
#include <atomic>
#include <QFile>
#include "lmms_basics.h"
@@ -53,11 +55,55 @@ public:
void setOutputFile( const QString& outputFile );
enum class DetailType {
NoteSetup,
Instruments,
Effects,
Mixing,
Count
};
constexpr static auto DetailCount = static_cast<std::size_t>(DetailType::Count);
int detailLoad(const DetailType type) const
{
return m_detailLoad[static_cast<std::size_t>(type)].load(std::memory_order_relaxed);
}
class Probe
{
public:
Probe(AudioEngineProfiler& profiler, AudioEngineProfiler::DetailType type)
: m_profiler(profiler)
, m_type(type)
{
profiler.startDetail(type);
}
~Probe() { m_profiler.finishDetail(m_type); }
Probe& operator=(const Probe&) = delete;
Probe(const Probe&) = delete;
Probe(Probe&&) = delete;
private:
AudioEngineProfiler &m_profiler;
const AudioEngineProfiler::DetailType m_type;
};
private:
void startDetail(const DetailType type) { m_detailTimer[static_cast<std::size_t>(type)].reset(); }
void finishDetail(const DetailType type)
{
m_detailTime[static_cast<std::size_t>(type)] = m_detailTimer[static_cast<std::size_t>(type)].elapsed();
}
MicroTimer m_periodTimer;
int m_cpuLoad;
std::atomic<float> m_cpuLoad;
QFile m_outputFile;
// Use arrays to avoid dynamic allocations in realtime code
std::array<MicroTimer, DetailCount> m_detailTimer;
std::array<int, DetailCount> m_detailTime{0};
std::array<std::atomic<float>, DetailCount> m_detailLoad{0};
};
} // namespace lmms

View File

@@ -26,6 +26,7 @@
#ifndef LMMS_GUI_CPU_LOAD_WIDGET_H
#define LMMS_GUI_CPU_LOAD_WIDGET_H
#include <algorithm>
#include <QTimer>
#include <QPixmap>
#include <QWidget>
@@ -40,6 +41,7 @@ namespace lmms::gui
class CPULoadWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(int stepSize MEMBER m_stepSize)
public:
CPULoadWidget( QWidget * _parent );
~CPULoadWidget() override = default;
@@ -54,6 +56,8 @@ protected slots:
private:
int stepSize() const { return std::max(1, m_stepSize); }
int m_currentLoad;
QPixmap m_temp;
@@ -64,6 +68,8 @@ private:
QTimer m_updateTimer;
int m_stepSize;
} ;