mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-25 23:40:51 +08:00
[ui] histogram update: added avg, median times, added color square for block name, added borders
This commit is contained in:
parent
c74744fae4
commit
33850d5abf
@ -727,6 +727,14 @@ void BlocksGraphicsView::onWindowActivationChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void BlocksGraphicsView::repaintHistogramImage()
|
||||
{
|
||||
if (m_pScrollbar != nullptr)
|
||||
{
|
||||
m_pScrollbar->repaintHistogramImage();
|
||||
}
|
||||
}
|
||||
|
||||
void BlocksGraphicsView::removePopup()
|
||||
{
|
||||
delete m_popupWidget;
|
||||
@ -2692,7 +2700,7 @@ void BlocksGraphicsView::onHierarchyFlagChange(bool)
|
||||
|
||||
void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t id)
|
||||
{
|
||||
if (m_pScrollbar == nullptr || m_pScrollbar->hystThread() == id)
|
||||
if (m_pScrollbar == nullptr || m_pScrollbar->histThread() == id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -265,6 +265,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void onWindowActivationChanged();
|
||||
void repaintHistogramImage();
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -81,7 +81,7 @@ inline EASY_CONSTEXPR_FCN uint16_t sizeOf() {
|
||||
return static_cast<uint16_t>(sizeof(typename profiler::StdType<type>::value_type));
|
||||
}
|
||||
|
||||
QString arrayToString(const profiler::ArbitraryValue& _serializedValue, int _index)
|
||||
static QString arrayToString(const profiler::ArbitraryValue& _serializedValue, int _index)
|
||||
{
|
||||
switch (_serializedValue.type())
|
||||
{
|
||||
@ -107,7 +107,7 @@ QString arrayToString(const profiler::ArbitraryValue& _serializedValue, int _ind
|
||||
}
|
||||
}
|
||||
|
||||
QString singleValueToString(const profiler::ArbitraryValue& _serializedValue)
|
||||
static QString singleValueToString(const profiler::ArbitraryValue& _serializedValue)
|
||||
{
|
||||
switch (_serializedValue.type())
|
||||
{
|
||||
@ -128,6 +128,32 @@ QString singleValueToString(const profiler::ArbitraryValue& _serializedValue)
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static QString shortenCountStringUnsigned(T count, int precision)
|
||||
{
|
||||
if (count >= 1000000)
|
||||
return QStringLiteral("%1m").arg(QString::number(count * 1e-6, 'f', precision));
|
||||
|
||||
if (count >= 1000)
|
||||
return QStringLiteral("%1k").arg(QString::number(count * 1e-3, 'f', precision));
|
||||
|
||||
return QString::number(count);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static QString shortenCountStringSigned(T count, int precision)
|
||||
{
|
||||
const auto absCount = std::abs(count);
|
||||
|
||||
if (absCount >= 1000000)
|
||||
return QStringLiteral("%1m").arg(QString::number(count * 1e-6, 'f', precision));
|
||||
|
||||
if (absCount >= 1000)
|
||||
return QStringLiteral("%1k").arg(QString::number(count * 1e-3, 'f', precision));
|
||||
|
||||
return QString::number(count);
|
||||
}
|
||||
|
||||
namespace profiler_gui {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -293,6 +319,28 @@ namespace profiler_gui {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QString shortenCountString(size_t count, int precision)
|
||||
{
|
||||
return shortenCountStringUnsigned(count, precision);
|
||||
}
|
||||
|
||||
QString shortenCountString(uint32_t count, int precision)
|
||||
{
|
||||
return shortenCountStringUnsigned(count, precision);
|
||||
}
|
||||
|
||||
QString shortenCountString(int64_t count, int precision)
|
||||
{
|
||||
return shortenCountStringSigned(count, precision);
|
||||
}
|
||||
|
||||
QString shortenCountString(int count, int precision)
|
||||
{
|
||||
return shortenCountStringSigned(count, precision);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QFont EFont(QFont::StyleHint _hint, const char* _family, int _size, int _weight)
|
||||
{
|
||||
QFont f(_family, _size, _weight);
|
||||
@ -479,4 +527,77 @@ namespace profiler_gui {
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
profiler::timestamp_t calculateMedian(const DurationsCountMap& durations)
|
||||
{
|
||||
if (durations.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
profiler::timestamp_t median = 0;
|
||||
|
||||
size_t total_count = 0;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
total_count += kv.second.count;
|
||||
}
|
||||
|
||||
if (total_count & 1)
|
||||
{
|
||||
const auto index = total_count >> 1;
|
||||
size_t i = 0;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
const auto count = kv.second.count;
|
||||
|
||||
i += count;
|
||||
if (i < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
median = kv.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto index2 = total_count >> 1;
|
||||
const auto index1 = index2 - 1;
|
||||
|
||||
size_t i = 0;
|
||||
bool i1 = false;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
const auto count = kv.second.count;
|
||||
|
||||
i += count;
|
||||
if (i < index1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!i1)
|
||||
{
|
||||
i1 = true;
|
||||
median = kv.first;
|
||||
}
|
||||
|
||||
if (i < index2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
median += kv.first;
|
||||
median >>= 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return median;
|
||||
}
|
||||
|
||||
} // end of namespace profiler_gui.
|
||||
|
@ -198,6 +198,13 @@ QString timeStringIntNs(TimeUnits _units, ::profiler::timestamp_t _interval);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QString shortenCountString(size_t count, int precision = 1);
|
||||
QString shortenCountString(uint32_t count, int precision = 1);
|
||||
QString shortenCountString(int64_t count, int precision = 1);
|
||||
QString shortenCountString(int count, int precision = 1);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline double percentReal(::profiler::timestamp_t _partial, ::profiler::timestamp_t _total) {
|
||||
return _total != 0 ? 100. * static_cast<double>(_partial) / static_cast<double>(_total) : 0.;
|
||||
}
|
||||
@ -243,6 +250,10 @@ void updateProperty(QWidget* widget, const char* name, T&& property)
|
||||
|
||||
void deleteTreeItem(QTreeWidgetItem* item);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
profiler::timestamp_t calculateMedian(const DurationsCountMap& durations);
|
||||
|
||||
} // END of namespace profiler_gui.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,6 +56,7 @@
|
||||
#ifndef EASY_PROFILER__GUI_COMMON_TYPES_H
|
||||
#define EASY_PROFILER__GUI_COMMON_TYPES_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <easy/reader.h>
|
||||
#include <QObject>
|
||||
@ -168,6 +169,16 @@ public:
|
||||
void restore() { m_ref = m_restore; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct Counter
|
||||
{
|
||||
T count = 0;
|
||||
};
|
||||
|
||||
using DurationsCountMap = std::map<profiler::timestamp_t, Counter<uint32_t> >;
|
||||
|
||||
} // END of namespace profiler_gui.
|
||||
|
||||
template <typename ... Args>
|
||||
|
@ -108,6 +108,7 @@ Globals::Globals()
|
||||
, enable_zero_length(true)
|
||||
, add_zero_blocks_to_hierarchy(false)
|
||||
, draw_graphics_items_borders(true)
|
||||
, draw_histogram_borders(true)
|
||||
, hide_narrow_children(false)
|
||||
, hide_minsize_blocks(false)
|
||||
, display_only_relevant_stats(false)
|
||||
|
@ -77,6 +77,8 @@ namespace profiler_gui {
|
||||
const QColor RULER_COLOR2 = QColor::fromRgba(0x40000000 | (::profiler::colors::Dark & 0x00ffffff));// 0x40408040);
|
||||
const QColor TEXT_COLOR = QColor::fromRgb(0xff504040);
|
||||
const QColor SYSTEM_BORDER_COLOR = QColor::fromRgb(0xffc4c4c4);
|
||||
|
||||
EASY_CONSTEXPR QRgb BLOCK_BORDER_COLOR = profiler::colors::Grey600 & 0x00ffffff;
|
||||
EASY_CONSTEXPR QRgb SELECTED_THREAD_BACKGROUND = 0xffe0e060;
|
||||
EASY_CONSTEXPR QRgb SELECTED_THREAD_FOREGROUND = 0xffffffff - (SELECTED_THREAD_BACKGROUND & 0x00ffffff);
|
||||
|
||||
@ -240,6 +242,7 @@ namespace profiler_gui {
|
||||
bool enable_zero_length; ///< Enable zero length blocks (if true, then such blocks will have width == 1 pixel on each scale)
|
||||
bool add_zero_blocks_to_hierarchy; ///< Enable adding zero blocks into hierarchy tree
|
||||
bool draw_graphics_items_borders; ///< Draw borders for graphics blocks or not
|
||||
bool draw_histogram_borders; ///< Draw borders for histogram columns or not
|
||||
bool hide_narrow_children; ///< Hide children for narrow graphics blocks (See blocks_narrow_size)
|
||||
bool hide_minsize_blocks; ///< Hide blocks which screen size is less than blocks_size_min
|
||||
bool display_only_relevant_stats; ///< Display only relevant information in ProfTreeWidget (excludes min, max, average times if there are only 1 calls number)
|
||||
|
@ -58,6 +58,8 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
|
||||
enum BlockItemState : int8_t
|
||||
{
|
||||
BLOCK_ITEM_DO_PAINT_FIRST = -2,
|
||||
@ -71,7 +73,7 @@ enum BlockItemState : int8_t
|
||||
EASY_CONSTEXPR int MIN_SYNC_SPACING = 1;
|
||||
EASY_CONSTEXPR int MIN_SYNC_SIZE = 3;
|
||||
EASY_CONSTEXPR int EVENT_HEIGHT = 4;
|
||||
EASY_CONSTEXPR QRgb BORDERS_COLOR = profiler::colors::Grey600 & 0x00ffffff;// 0x00686868;
|
||||
EASY_CONSTEXPR auto BORDERS_COLOR = profiler_gui::BLOCK_BORDER_COLOR;
|
||||
|
||||
inline QRgb selectedItemBorderColor(profiler::color_t _color) {
|
||||
return ::profiler_gui::isLightColor(_color, 192) ? profiler::colors::Black : profiler::colors::RichRed;
|
||||
@ -91,7 +93,14 @@ EASY_FORCE_INLINE void restoreItemFont(QPainter* /*painter*/)
|
||||
//painter->setFont(EASY_GLOBALS.font.item);
|
||||
}
|
||||
|
||||
const QPen HIGHLIGHTER_PEN = ([]() -> QPen { QPen p(profiler::colors::Black); p.setStyle(Qt::DotLine); p.setWidth(2); return p; })();
|
||||
const QPen HIGHLIGHTER_PEN = ([]() -> QPen {
|
||||
QPen p(profiler::colors::Black);
|
||||
p.setStyle(Qt::DotLine);
|
||||
p.setWidth(2);
|
||||
return p;
|
||||
})();
|
||||
|
||||
} // end of namespace <noname>.
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
|
@ -61,9 +61,12 @@
|
||||
#include "graphics_scrollbar.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EASY_CONSTEXPR int HIST_COLUMN_MIN_HEIGHT = 2;
|
||||
EASY_CONSTEXPR qreal HIST_COLUMN_MIN_WIDTH_WITH_BORDER = 3;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -78,16 +81,24 @@ inline qreal calculate_color2(qreal, qreal duration, qreal k)
|
||||
return std::min(sqr(sqr(duration)) * k, 0.9999999);
|
||||
}
|
||||
|
||||
} // end of namespace <noname>.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GraphicsHistogramItem::GraphicsHistogramItem() : Parent()
|
||||
, m_threadDuration(0)
|
||||
, m_threadProfiledTime(0)
|
||||
, m_threadWaitTime(0)
|
||||
, m_pSource(nullptr)
|
||||
, m_workerTopDuration(0)
|
||||
, m_workerBottomDuration(0)
|
||||
, m_blockTotalDuraion(0)
|
||||
, m_threadDuration(0)
|
||||
, m_threadProfiledTime(0)
|
||||
, m_threadWaitTime(0)
|
||||
, m_medianDuration(0)
|
||||
, m_avgDuration(0)
|
||||
, m_medianDurationFull(0)
|
||||
, m_avgDurationFull(0)
|
||||
, m_workerMedianDuration(0)
|
||||
, m_workerAvgDuration(0)
|
||||
, m_pSource(nullptr)
|
||||
, m_pProfilerThread(nullptr)
|
||||
, m_threadId(0)
|
||||
, m_blockId(profiler_gui::numeric_max<decltype(m_blockId)>())
|
||||
@ -161,7 +172,6 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
|
||||
const auto dtime = m_topValue - m_bottomValue;
|
||||
const auto coeff = m_boundingRect.height() / (dtime > 1e-3 ? dtime : 1.);
|
||||
|
||||
QRectF rect;
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
//QRgb previousColor = 0;
|
||||
|
||||
@ -178,11 +188,33 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
|
||||
|
||||
qreal top_width = width, bottom_width = width;
|
||||
const auto font_h = widget->fontHeight();
|
||||
rect.setRect(0, m_boundingRect.top() - widget->margin(), width - 3, font_h);
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview");
|
||||
QRectF bottomRect(3, bottom + 2, width - 3, font_h);
|
||||
QRectF topRect(3, m_boundingRect.top() - widget->margin(), width - 3, font_h);
|
||||
QRectF textBounds;
|
||||
|
||||
// MODE
|
||||
{
|
||||
_painter->setPen(Qt::blue);
|
||||
_painter->drawText(
|
||||
topRect,
|
||||
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip | Qt::TextIncludeTrailingSpaces,
|
||||
QStringLiteral("MODE: "),
|
||||
&textBounds
|
||||
);
|
||||
topRect.adjust(textBounds.width(), 0, 0, 0);
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(
|
||||
topRect,
|
||||
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip,
|
||||
bindMode ? "Zoom" : "Overview",
|
||||
&textBounds
|
||||
);
|
||||
topRect.adjust(textBounds.width() + 3, 0, 0, 0);
|
||||
}
|
||||
|
||||
// TOP & BOTTOM duration
|
||||
if (!isEmpty() && !m_topDurationStr.isEmpty())
|
||||
{
|
||||
if (m_timeUnits != EASY_GLOBALS.time_units)
|
||||
@ -190,17 +222,24 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
|
||||
m_timeUnits = EASY_GLOBALS.time_units;
|
||||
m_topDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_topValue, 3);
|
||||
m_bottomDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_bottomValue, 3);
|
||||
|
||||
if (m_avgDuration != 0 || m_medianDuration != 0)
|
||||
{
|
||||
m_medianDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_medianDuration, 3);
|
||||
m_avgDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_avgDuration, 3);
|
||||
}
|
||||
}
|
||||
|
||||
//auto fm = _painter->fontMetrics();
|
||||
//top_width -= fm.width(m_topDurationStr) + 7;
|
||||
|
||||
_painter->setPen(m_topValue < m_maxValue ? QColor(Qt::darkRed) : profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_topDurationStr);
|
||||
_painter->drawText(topRect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_topDurationStr, &textBounds);
|
||||
topRect.adjust(0, 0, -textBounds.width() - 3, 0);
|
||||
|
||||
rect.setRect(0, bottom + 2, width - 3, font_h);
|
||||
_painter->setPen(m_bottomValue > m_minValue ? QColor(Qt::darkRed) : profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_bottomDurationStr);
|
||||
_painter->drawText(bottomRect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_bottomDurationStr, &textBounds);
|
||||
bottomRect.adjust(0, 0, -textBounds.width() - 3, 0);
|
||||
}
|
||||
|
||||
_painter->setPen(Qt::darkGray);
|
||||
@ -209,35 +248,70 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
|
||||
|
||||
paintMouseIndicator(_painter, m_boundingRect.top(), bottom, width, m_boundingRect.height(), top_width, m_mousePos.y(), dtime, font_h);
|
||||
|
||||
if (!isEmpty() && m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
|
||||
// MEDIAN & EXPECTED FRAME TIME
|
||||
if (!isEmpty())
|
||||
{
|
||||
// Draw marker displaying expected frame_time step
|
||||
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashLine);
|
||||
const qreal mdn = m_medianDuration * 1e-3;
|
||||
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h > (bottom + boundary))
|
||||
w = bottom_width;
|
||||
if (m_bottomValue < mdn && mdn < m_topValue)
|
||||
{
|
||||
// Draw marker displaying expected frame_time step
|
||||
const auto h = bottom - (mdn - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashDotDotLine);
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h > (bottom + boundary))
|
||||
w = bottom_width;
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
}
|
||||
|
||||
if (m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
|
||||
{
|
||||
// Draw marker displaying expected frame_time step
|
||||
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashLine);
|
||||
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h > (bottom + boundary))
|
||||
w = bottom_width;
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
rect.setRect(0, bottom + 2, width, font_h);
|
||||
const auto eventsSize = m_pProfilerThread->events.size();
|
||||
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip, QString("%1 | duration: %2 | profiled: %3 (%4%) | wait: %5 (%6%) | %7 frames | %8 blocks | %9 markers")
|
||||
.arg(m_threadName)
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadDuration))
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadProfiledTime))
|
||||
.arg(m_threadDuration ? QString::number(100. * (double)m_threadProfiledTime / (double)m_threadDuration, 'f', 2) : QString("0"))
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadWaitTime))
|
||||
.arg(m_threadDuration ? QString::number(100. * (double)m_threadWaitTime / (double)m_threadDuration, 'f', 2) : QString("0"))
|
||||
.arg(m_pProfilerThread->frames_number)
|
||||
.arg(m_pProfilerThread->blocks_number - eventsSize)
|
||||
.arg(eventsSize));
|
||||
const auto eventsCount = m_pProfilerThread->events.size();
|
||||
const auto blocksCount = m_pProfilerThread->blocks_number - eventsCount;
|
||||
|
||||
QString durationsStr;
|
||||
if (!m_medianDurationStr.isEmpty() || !m_avgDurationStr.isEmpty())
|
||||
{
|
||||
durationsStr = QString("avg: %1 | mdn: %2 | ").arg(m_avgDurationStr).arg(m_medianDurationStr);
|
||||
}
|
||||
|
||||
_painter->drawText(topRect, Qt::AlignCenter, m_threadName);
|
||||
|
||||
_painter->drawText(bottomRect, Qt::AlignCenter,
|
||||
QStringLiteral("time: %1 | profiled: %2 (%3%) | wait: %4 (%5%) | %6%7 frames | %8 blocks | %9 markers")
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadDuration))
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadProfiledTime))
|
||||
.arg(m_threadDuration ? QString::number(100. * (double) m_threadProfiledTime / (double) m_threadDuration, 'f', 2)
|
||||
: QString("0"))
|
||||
.arg(profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, m_threadWaitTime))
|
||||
.arg(m_threadDuration ? QString::number(100. * (double) m_threadWaitTime / (double) m_threadDuration, 'f', 2)
|
||||
: QString("0"))
|
||||
.arg(durationsStr)
|
||||
.arg(profiler_gui::shortenCountString(m_pProfilerThread->frames_number))
|
||||
.arg(profiler_gui::shortenCountString(blocksCount))
|
||||
.arg(profiler_gui::shortenCountString(eventsCount))
|
||||
);
|
||||
|
||||
_painter->restore();
|
||||
}
|
||||
@ -252,7 +326,6 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
|
||||
const auto dtime = m_topValue - m_bottomValue;
|
||||
const auto coeff = m_boundingRect.height() / (dtime > 1e-3 ? dtime : 1.);
|
||||
|
||||
QRectF rect;
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
//QRgb previousColor = 0;
|
||||
|
||||
@ -270,11 +343,33 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
|
||||
|
||||
qreal top_width = width, bottom_width = width;
|
||||
const auto font_h = widget->fontHeight();
|
||||
rect.setRect(0, m_boundingRect.top() - widget->margin(), width - 3, font_h);
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview");
|
||||
QRectF bottomRect(3, bottom + 2, width - 3, font_h);
|
||||
QRectF topRect(3, m_boundingRect.top() - widget->margin(), width - 3, font_h);
|
||||
QRectF textBounds;
|
||||
|
||||
// MODE
|
||||
{
|
||||
_painter->setPen(Qt::blue);
|
||||
_painter->drawText(
|
||||
topRect,
|
||||
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip | Qt::TextIncludeTrailingSpaces,
|
||||
QStringLiteral("MODE: "),
|
||||
&textBounds
|
||||
);
|
||||
topRect.adjust(textBounds.width(), 0, 0, 0);
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(
|
||||
topRect,
|
||||
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip,
|
||||
bindMode ? "Zoom" : "Overview",
|
||||
&textBounds
|
||||
);
|
||||
topRect.adjust(textBounds.width() + 3, 0, 0, 0);
|
||||
}
|
||||
|
||||
// TOP & BOTTOM duration
|
||||
if (!isEmpty() && !m_topDurationStr.isEmpty())
|
||||
{
|
||||
if (m_timeUnits != EASY_GLOBALS.time_units)
|
||||
@ -282,17 +377,24 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
|
||||
m_timeUnits = EASY_GLOBALS.time_units;
|
||||
m_topDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_topValue, 3);
|
||||
m_bottomDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_bottomValue, 3);
|
||||
|
||||
if (m_avgDuration != 0 || m_medianDuration != 0)
|
||||
{
|
||||
m_medianDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_medianDuration, 3);
|
||||
m_avgDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_avgDuration, 3);
|
||||
}
|
||||
}
|
||||
|
||||
//auto fm = _painter->fontMetrics();
|
||||
//top_width -= fm.width(m_topDurationStr) + 7;
|
||||
|
||||
_painter->setPen(m_topValue < m_maxValue ? QColor(Qt::darkRed) : profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_topDurationStr);
|
||||
_painter->drawText(topRect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_topDurationStr, &textBounds);
|
||||
topRect.adjust(0, 0, -textBounds.width() - 3, 0);
|
||||
|
||||
rect.setRect(0, bottom + 2, width - 3, font_h);
|
||||
_painter->setPen(m_bottomValue > m_minValue ? QColor(Qt::darkRed) : profiler_gui::TEXT_COLOR);
|
||||
_painter->drawText(rect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_bottomDurationStr);
|
||||
_painter->drawText(bottomRect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, m_bottomDurationStr, &textBounds);
|
||||
bottomRect.adjust(0, 0, -textBounds.width() - 3, 0);
|
||||
}
|
||||
|
||||
_painter->setPen(Qt::darkGray);
|
||||
@ -301,44 +403,89 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
|
||||
|
||||
paintMouseIndicator(_painter, m_boundingRect.top(), bottom, width, m_boundingRect.height(), top_width, m_mousePos.y(), dtime, font_h);
|
||||
|
||||
if (!isEmpty() && m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
|
||||
// MEDIAN & EXPECTED FRAME TIME
|
||||
if (!isEmpty())
|
||||
{
|
||||
// Draw marker displaying required frame_time step
|
||||
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashLine);
|
||||
const qreal mdn = m_medianDuration * 1e-3;
|
||||
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h >(bottom + boundary))
|
||||
w = bottom_width;
|
||||
if (m_bottomValue < mdn && mdn < m_topValue)
|
||||
{
|
||||
// Draw marker displaying expected frame_time step
|
||||
const auto h = bottom - (mdn - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashDotDotLine);
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h > (bottom + boundary))
|
||||
w = bottom_width;
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
}
|
||||
|
||||
if (m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
|
||||
{
|
||||
// Draw marker displaying required frame_time step
|
||||
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
|
||||
_painter->setPen(Qt::DashLine);
|
||||
|
||||
auto w = width;
|
||||
const auto boundary = widget->margin() - font_h;
|
||||
if (h < (m_boundingRect.top() - boundary))
|
||||
w = top_width;
|
||||
else if (h > (bottom + boundary))
|
||||
w = bottom_width;
|
||||
|
||||
_painter->drawLine(QLineF(0, h, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
const auto colorIndicatorSize = font_h * 2 / 3;
|
||||
|
||||
_painter->setBrush(QColor::fromRgba(easyDescriptor(m_blockId).color()));
|
||||
_painter->setPen(profiler_gui::BLOCK_BORDER_COLOR);
|
||||
_painter->drawRect(QRectF(bottomRect.left(), bottomRect.top() + 1 + font_h / 6., colorIndicatorSize, colorIndicatorSize));
|
||||
bottomRect.adjust(colorIndicatorSize + 3, 0, 0, 0);
|
||||
|
||||
_painter->setPen(profiler_gui::TEXT_COLOR);
|
||||
rect.setRect(0, bottom + 2, width, font_h);
|
||||
_painter->drawText(topRect, Qt::AlignCenter, m_threadName);
|
||||
|
||||
_painter->drawText(bottomRect, Qt::AlignLeft, m_blockName, &textBounds);
|
||||
bottomRect.adjust(textBounds.width() + 3, 0, 0, 0);
|
||||
|
||||
_painter->drawText(bottomRect, Qt::AlignLeft, QStringLiteral("| %1").arg(m_blockType), &textBounds);
|
||||
bottomRect.adjust(textBounds.width() + 3, 0, 0, 0);
|
||||
|
||||
if (!items.empty())
|
||||
{
|
||||
QString durationsStr;
|
||||
if (!m_medianDurationStr.isEmpty() || !m_avgDurationStr.isEmpty())
|
||||
{
|
||||
durationsStr = QString("avg: %1 | mdn: %2 | ").arg(m_avgDurationStr).arg(m_medianDurationStr);
|
||||
}
|
||||
|
||||
if (m_threadProfiledTime != 0)
|
||||
{
|
||||
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
|
||||
QString("%1 | %2 | %3 calls | %4% of thread profiled time")
|
||||
.arg(m_threadName).arg(m_blockName).arg(items.size())
|
||||
.arg(QString::number(100. * (double)m_blockTotalDuraion / (double)m_threadProfiledTime, 'f', 2)));
|
||||
_painter->drawText(bottomRect, Qt::AlignCenter,
|
||||
QStringLiteral("%1 calls | %2%3% of thread profiled time")
|
||||
.arg(items.size())
|
||||
.arg(durationsStr)
|
||||
.arg(QString::number(100. * (double) m_blockTotalDuraion / (double) m_threadProfiledTime, 'f', 2))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
|
||||
QString("%1 | %2 | %3 calls | 100% of thread profiled time")
|
||||
.arg(m_threadName).arg(m_blockName).arg(items.size()));
|
||||
_painter->drawText(bottomRect, Qt::AlignCenter,
|
||||
QStringLiteral("%1 calls | %2100% of thread profiled time")
|
||||
.arg(items.size())
|
||||
.arg(durationsStr)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip, QString("%1 | %2 | 0 calls").arg(m_threadName).arg(m_blockName));
|
||||
_painter->drawText(bottomRect, Qt::AlignCenter, QStringLiteral("0 calls"));
|
||||
}
|
||||
|
||||
_painter->restore();
|
||||
@ -379,7 +526,12 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
m_boundaryTimer.stop();
|
||||
|
||||
m_blockName.clear();
|
||||
m_blockType = QStringLiteral("Thread");
|
||||
m_blockTotalDuraion = 0;
|
||||
m_medianDuration = 0;
|
||||
m_avgDuration = 0;
|
||||
m_medianDurationFull = 0;
|
||||
m_avgDurationFull = 0;
|
||||
|
||||
m_imageOriginUpdate = m_imageOrigin = 0;
|
||||
m_imageScaleUpdate = m_imageScale = 1;
|
||||
@ -388,6 +540,11 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
setEmpty(true);
|
||||
{ profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
|
||||
|
||||
m_topDurationStr.clear();
|
||||
m_bottomDurationStr.clear();
|
||||
m_medianDurationStr.clear();
|
||||
m_avgDurationStr.clear();
|
||||
|
||||
setImageUpdatePermitted(false);
|
||||
m_regime = Hist_Pointer;
|
||||
m_pSource = _items;
|
||||
@ -423,15 +580,25 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
m_maxValue = 0;
|
||||
m_minValue = 1e30;
|
||||
|
||||
size_t totalCount = 0;
|
||||
profiler_gui::DurationsCountMap durations;
|
||||
bool empty = true;
|
||||
for (const auto& item : *source)
|
||||
{
|
||||
if (isReady())
|
||||
return;
|
||||
|
||||
if (easyDescriptor(easyBlock(item.block).tree.node->id()).type() == profiler::BlockType::Event)
|
||||
auto& block = easyBlock(item.block).tree;
|
||||
auto& desc = easyDescriptor(block.node->id());
|
||||
if (desc.type() != profiler::BlockType::Block)
|
||||
continue;
|
||||
|
||||
const auto duration = block.node->duration();
|
||||
|
||||
++totalCount;
|
||||
++durations[duration].count;
|
||||
m_avgDuration += duration;
|
||||
|
||||
const auto w = item.width();
|
||||
|
||||
if (w > m_maxValue)
|
||||
@ -443,6 +610,12 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
empty = false;
|
||||
}
|
||||
|
||||
if (!empty)
|
||||
{
|
||||
m_avgDuration /= totalCount;
|
||||
m_medianDuration = profiler_gui::calculateMedian(durations);
|
||||
}
|
||||
|
||||
if ((m_maxValue - m_minValue) < 1e-3)
|
||||
{
|
||||
if (m_minValue > 0.1)
|
||||
@ -464,10 +637,13 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
m_topDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_topValue, 3);
|
||||
m_bottomDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_bottomValue, 3);
|
||||
}
|
||||
else
|
||||
|
||||
if (m_avgDuration != 0 || m_medianDuration != 0)
|
||||
{
|
||||
m_topDurationStr.clear();
|
||||
m_bottomDurationStr.clear();
|
||||
m_avgDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_avgDuration, 3);
|
||||
m_medianDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_medianDuration, 3);
|
||||
m_medianDurationFull = m_medianDuration;
|
||||
m_avgDurationFull = m_avgDuration;
|
||||
}
|
||||
|
||||
setEmpty(empty);
|
||||
@ -483,8 +659,6 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
|
||||
if (m_pSource == nullptr)
|
||||
{
|
||||
m_pProfilerThread = nullptr;
|
||||
m_topDurationStr.clear();
|
||||
m_bottomDurationStr.clear();
|
||||
m_threadName.clear();
|
||||
hide();
|
||||
}
|
||||
@ -505,8 +679,15 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
m_pSource = nullptr;
|
||||
m_topDurationStr.clear();
|
||||
m_bottomDurationStr.clear();
|
||||
m_medianDurationStr.clear();
|
||||
m_avgDurationStr.clear();
|
||||
m_blockName.clear();
|
||||
m_blockType.clear();
|
||||
m_blockTotalDuraion = 0;
|
||||
m_medianDuration = 0;
|
||||
m_avgDuration = 0;
|
||||
m_medianDurationFull = 0;
|
||||
m_avgDurationFull = 0;
|
||||
|
||||
m_imageOriginUpdate = m_imageOrigin = 0;
|
||||
m_imageScaleUpdate = m_imageScale = 1;
|
||||
@ -520,7 +701,31 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
|
||||
if (m_threadId != 0 && !profiler_gui::is_max(m_blockId))
|
||||
{
|
||||
m_blockName = profiler_gui::toUnicode(easyDescriptor(m_blockId).name());
|
||||
auto& desc = easyDescriptor(m_blockId);
|
||||
m_blockName = profiler_gui::toUnicode(desc.name());
|
||||
|
||||
switch (desc.type())
|
||||
{
|
||||
case profiler::BlockType::Block:
|
||||
{
|
||||
m_blockType = QStringLiteral("Block");
|
||||
break;
|
||||
}
|
||||
|
||||
case profiler::BlockType::Event:
|
||||
{
|
||||
m_blockType = QStringLiteral("Event");
|
||||
break;
|
||||
}
|
||||
|
||||
case profiler::BlockType::Value:
|
||||
{
|
||||
m_blockType = QStringLiteral("Value");
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
const auto& root = EASY_GLOBALS.profiler_blocks[_thread_id];
|
||||
m_threadName = profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root, EASY_GLOBALS.hex_thread_id);
|
||||
@ -564,6 +769,8 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
|
||||
const bool has_selected_block = !profiler_gui::is_max(selected_block);
|
||||
|
||||
size_t totalCount = 0;
|
||||
profiler_gui::DurationsCountMap durations;
|
||||
for (auto frame : profiler_thread.children)
|
||||
{
|
||||
const auto& frame_block = easyBlock(frame).tree;
|
||||
@ -578,6 +785,8 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
if (w < m_minValue)
|
||||
m_minValue = w;
|
||||
|
||||
++totalCount;
|
||||
++durations[w].count;
|
||||
m_blockTotalDuraion += w;
|
||||
}
|
||||
|
||||
@ -611,6 +820,8 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
if (w < m_minValue)
|
||||
m_minValue = w;
|
||||
|
||||
++totalCount;
|
||||
++durations[w].count;
|
||||
m_blockTotalDuraion += w;
|
||||
}
|
||||
|
||||
@ -633,6 +844,8 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
{
|
||||
m_topDurationStr.clear();
|
||||
m_bottomDurationStr.clear();
|
||||
m_medianDurationStr.clear();
|
||||
m_avgDurationStr.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -659,8 +872,20 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
|
||||
}
|
||||
}
|
||||
|
||||
m_avgDuration = m_blockTotalDuraion / totalCount;
|
||||
m_medianDuration = profiler_gui::calculateMedian(durations);
|
||||
|
||||
m_medianDurationFull = m_medianDuration;
|
||||
m_avgDurationFull = m_avgDuration;
|
||||
|
||||
m_topDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_maxValue, 3);
|
||||
m_bottomDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_minValue, 3);
|
||||
|
||||
if (m_avgDuration != 0 || m_medianDuration != 0)
|
||||
{
|
||||
m_avgDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_avgDuration, 3);
|
||||
m_medianDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_medianDuration, 3);
|
||||
}
|
||||
}
|
||||
|
||||
m_topValue = m_maxValue;
|
||||
@ -831,9 +1056,10 @@ bool GraphicsHistogramItem::updateImage()
|
||||
const auto frameTime = EASY_GLOBALS.frame_time;
|
||||
const auto beginTime = EASY_GLOBALS.begin_time;
|
||||
const auto autoHeight = EASY_GLOBALS.auto_adjust_histogram_height;
|
||||
const auto drawBorders = EASY_GLOBALS.draw_histogram_borders;
|
||||
m_worker.enqueue([=] {
|
||||
updateImageAsync(rect, regime, scale, left, right, right - left, value, window, top, bottom, bindMode,
|
||||
frameTime, beginTime, autoHeight);
|
||||
frameTime, beginTime, autoHeight, drawBorders);
|
||||
}, m_bReady);
|
||||
|
||||
return true;
|
||||
@ -849,12 +1075,29 @@ void GraphicsHistogramItem::onImageUpdated()
|
||||
m_topDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_topValue, 3);
|
||||
m_bottomDurationStr = profiler_gui::timeStringReal(m_timeUnits, m_bottomValue, 3);
|
||||
}
|
||||
|
||||
if (static_cast<const GraphicsSliderArea*>(scene()->parent())->bindMode())
|
||||
{
|
||||
m_medianDuration = m_workerMedianDuration;
|
||||
m_avgDuration = m_workerAvgDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_medianDuration = m_medianDurationFull;
|
||||
m_avgDuration = m_avgDurationFull;
|
||||
}
|
||||
|
||||
if (m_avgDuration != 0 || m_medianDuration != 0)
|
||||
{
|
||||
m_medianDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_medianDuration, 3);
|
||||
m_avgDurationStr = profiler_gui::timeStringRealNs(m_timeUnits, m_avgDuration, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _regime, qreal _current_scale,
|
||||
qreal _minimum, qreal _maximum, qreal _range,
|
||||
qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration,
|
||||
bool _bindMode, float _frame_time, profiler::timestamp_t _begin_time, bool _autoAdjustHist)
|
||||
bool _bindMode, float _frame_time, profiler::timestamp_t _begin_time, bool _autoAdjustHist, bool _drawBorders)
|
||||
{
|
||||
const auto bottom = _boundingRect.height();//_boundingRect.bottom();
|
||||
const auto screenWidth = _boundingRect.width() * _current_scale;
|
||||
@ -899,6 +1142,11 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
auto const calculate_color = gotFrame ? calculate_color2 : calculate_color1;
|
||||
auto const k = gotFrame ? sqr(sqr(frameCoeff)) : 1.0 / _boundingRect.height();
|
||||
|
||||
size_t totalCount = 0;
|
||||
m_workerMedianDuration = 0;
|
||||
m_workerAvgDuration = 0;
|
||||
profiler_gui::DurationsCountMap durations;
|
||||
|
||||
if (_regime == Hist_Pointer)
|
||||
{
|
||||
const auto& items = *m_pSource;
|
||||
@ -914,7 +1162,7 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
realScale *= viewScale;
|
||||
offset = _minimum * realScale;
|
||||
|
||||
first = std::lower_bound(items.begin(), items.end(), _minimum, [](const profiler_gui::EasyBlockItem& _item, qreal _value)
|
||||
first = std::lower_bound(items.begin(), items.end(), _minimum, [] (const profiler_gui::EasyBlockItem& _item, qreal _value)
|
||||
{
|
||||
return _item.left() < _value;
|
||||
});
|
||||
@ -977,6 +1225,10 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
const auto dtime = _top_duration - _bottom_duration;
|
||||
const auto coeff = _boundingRect.height() / (dtime > 1e-3 ? dtime : 1.);
|
||||
|
||||
const qreal minWidth = _drawBorders ? HIST_COLUMN_MIN_WIDTH_WITH_BORDER : 1.;
|
||||
if (_drawBorders)
|
||||
p.setPen(profiler_gui::BLOCK_BORDER_COLOR);
|
||||
|
||||
for (auto it = first, end = items.end(); it != end; ++it)
|
||||
{
|
||||
// Draw rectangle
|
||||
@ -986,16 +1238,97 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
if (it->right() < _minimum)
|
||||
continue;
|
||||
|
||||
const qreal item_x = it->left() * realScale - offset;
|
||||
const qreal item_w = std::max(it->width() * realScale, 1.0);
|
||||
const qreal item_r = item_x + item_w;
|
||||
const qreal h = it->width() <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
(it->width() > _top_duration ? maxColumnHeight : (it->width() - _bottom_duration) * coeff);
|
||||
if (_bindMode)
|
||||
{
|
||||
// calculate avg and median
|
||||
const auto duration = easyBlock(it->block).tree.node->duration();
|
||||
m_workerAvgDuration += duration;
|
||||
++totalCount;
|
||||
++durations[duration].count;
|
||||
}
|
||||
|
||||
auto maxItemWidth = it->width();
|
||||
|
||||
// calculate column width and height
|
||||
qreal item_x = it->left() * realScale - offset;
|
||||
qreal item_w = it->width() * realScale;
|
||||
qreal item_r = item_x + item_w;
|
||||
const auto width = it->width();
|
||||
qreal h = width <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
(width > _top_duration ? maxColumnHeight : (width - _bottom_duration) * coeff);
|
||||
|
||||
if (_drawBorders)
|
||||
{
|
||||
if (item_r < previous_x)
|
||||
{
|
||||
item_w -= previous_x - item_r;
|
||||
item_x = previous_x;
|
||||
item_r = item_x + item_w;
|
||||
}
|
||||
|
||||
// if column width < minWidth then try to merge several columns together
|
||||
auto jt = it;
|
||||
while (item_w < minWidth && jt != end)
|
||||
{
|
||||
if (jt->left() > _maximum)
|
||||
break;
|
||||
|
||||
const qreal jx = jt->left() * realScale - offset;
|
||||
auto dx = jx - item_r;
|
||||
if (dx > std::max(item_w, minWidth))
|
||||
{
|
||||
item_w = minWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
const qreal jw = jt->width() * realScale;
|
||||
if (jw > (minWidth + item_w))
|
||||
{
|
||||
item_w = minWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto jwidth = jt->width();
|
||||
const qreal jh = jwidth <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
(jwidth > _top_duration ? maxColumnHeight : (jwidth - _bottom_duration) * coeff);
|
||||
|
||||
item_w += jw;
|
||||
h = std::max(h, jh);
|
||||
maxItemWidth = std::max(maxItemWidth, jwidth);
|
||||
++jt;
|
||||
}
|
||||
|
||||
item_r = item_x + item_w;
|
||||
|
||||
if (_bindMode)
|
||||
{
|
||||
// if merged several columns then avg and median should be calculated for these columns too
|
||||
for (auto it2 = it; it2 != jt; ++it2)
|
||||
{
|
||||
const auto duration = easyBlock(it2->block).tree.node->duration();
|
||||
m_workerAvgDuration += duration;
|
||||
++totalCount;
|
||||
++durations[duration].count;
|
||||
}
|
||||
}
|
||||
|
||||
if (jt != it)
|
||||
{
|
||||
// bypass merged columns
|
||||
it = jt;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
else if (item_w < 1)
|
||||
{
|
||||
item_w = 1;
|
||||
item_r = item_x + 1;
|
||||
}
|
||||
|
||||
if (h < previous_h && item_r < previous_x)
|
||||
continue;
|
||||
|
||||
const auto col = calculate_color(h, it->width(), k);
|
||||
const auto col = calculate_color(h, maxItemWidth, k);
|
||||
const auto color = 0x00ffffff & QColor::fromHsvF((1.0 - col) * 0.375, 0.85, 0.85).rgb();
|
||||
|
||||
if (previousColor != color)
|
||||
@ -1100,6 +1433,10 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
const auto dtime = _top_duration - _bottom_duration;
|
||||
const auto coeff = _boundingRect.height() / (dtime > 1e-3 ? dtime : 1.);
|
||||
|
||||
const qreal minWidth = _drawBorders ? HIST_COLUMN_MIN_WIDTH_WITH_BORDER : 1.;
|
||||
if (_drawBorders)
|
||||
p.setPen(profiler_gui::BLOCK_BORDER_COLOR);
|
||||
|
||||
for (auto it = first, end = m_selectedBlocks.end(); it != end; ++it)
|
||||
{
|
||||
// Draw rectangle
|
||||
@ -1113,17 +1450,100 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
if (endTime < _minimum)
|
||||
continue;
|
||||
|
||||
if (_bindMode)
|
||||
{
|
||||
// calculate avg and median
|
||||
const auto duration = item->duration();
|
||||
m_workerAvgDuration += duration;
|
||||
++totalCount;
|
||||
++durations[duration].count;
|
||||
}
|
||||
|
||||
const qreal duration = item->duration() * 1e-3;
|
||||
const qreal item_x = (beginTime * realScale - offset) * 1e-3;
|
||||
const qreal item_w = std::max(duration * realScale, 1.0);
|
||||
const qreal item_r = item_x + item_w;
|
||||
const auto h = duration <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
auto maxItemDuration = duration;
|
||||
|
||||
// calculate column width and height
|
||||
qreal item_x = (beginTime * realScale - offset) * 1e-3;
|
||||
qreal item_w = duration * realScale;
|
||||
qreal item_r = item_x + item_w;
|
||||
auto h = duration <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
(duration > _top_duration ? maxColumnHeight : (duration - _bottom_duration) * coeff);
|
||||
|
||||
if (_drawBorders)
|
||||
{
|
||||
if (item_r < previous_x)
|
||||
{
|
||||
item_w -= previous_x - item_r;
|
||||
item_x = previous_x;
|
||||
item_r = item_x + item_w;
|
||||
}
|
||||
|
||||
// if column width < minWidth then try to merge several columns together
|
||||
auto jt = it;
|
||||
while (item_w < minWidth && jt != end)
|
||||
{
|
||||
const auto jtem = easyBlock(*jt).tree.node;
|
||||
const auto jbeginTime = jtem->begin() - _begin_time;
|
||||
if (jbeginTime > _maximum)
|
||||
break;
|
||||
|
||||
const qreal jduration = jtem->duration() * 1e-3;
|
||||
|
||||
const qreal jx = ((jtem->begin() - _begin_time) * realScale - offset) * 1e-3;
|
||||
auto dx = jx - item_r;
|
||||
if (dx > std::max(item_w, minWidth))
|
||||
{
|
||||
item_w = minWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
const qreal jw = jduration * realScale;
|
||||
if (jw > (minWidth + item_w))
|
||||
{
|
||||
item_w = minWidth;
|
||||
break;
|
||||
}
|
||||
|
||||
const qreal jh = jduration <= _bottom_duration ? HIST_COLUMN_MIN_HEIGHT :
|
||||
(jduration > _top_duration ? maxColumnHeight : (jduration - _bottom_duration) * coeff);
|
||||
|
||||
item_w += jw;
|
||||
h = std::max(h, jh);
|
||||
maxItemDuration = std::max(maxItemDuration, jduration);
|
||||
++jt;
|
||||
}
|
||||
|
||||
item_r = item_x + item_w;
|
||||
|
||||
if (_bindMode)
|
||||
{
|
||||
// if merged several columns then avg and median should be calculated for these columns too
|
||||
for (auto it2 = it; it2 != jt; ++it2)
|
||||
{
|
||||
const auto duration = easyBlock(*it2).tree.node->duration();
|
||||
m_workerAvgDuration += duration;
|
||||
++totalCount;
|
||||
++durations[duration].count;
|
||||
}
|
||||
}
|
||||
|
||||
if (jt != it)
|
||||
{
|
||||
// bypass merged columns
|
||||
it = jt;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
else if (item_w < 1)
|
||||
{
|
||||
item_w = 1;
|
||||
item_r = item_x + 1;
|
||||
}
|
||||
|
||||
if (h < previous_h && item_r < previous_x)
|
||||
continue;
|
||||
|
||||
const auto col = calculate_color(h, duration, k);
|
||||
const auto col = calculate_color(h, maxItemDuration, k);
|
||||
const auto color = 0x00ffffff & QColor::fromHsvF((1.0 - col) * 0.375, 0.85, 0.85).rgb();
|
||||
|
||||
if (previousColor != color)
|
||||
@ -1145,6 +1565,12 @@ void GraphicsHistogramItem::updateImageAsync(QRectF _boundingRect, HistRegime _r
|
||||
m_workerTopDuration = _top_duration;
|
||||
m_workerBottomDuration = _bottom_duration;
|
||||
|
||||
if (_bindMode)
|
||||
{
|
||||
m_workerAvgDuration /= totalCount;
|
||||
m_workerMedianDuration = profiler_gui::calculateMedian(durations);
|
||||
}
|
||||
|
||||
setReady(true);
|
||||
}
|
||||
|
||||
@ -1166,7 +1592,7 @@ GraphicsScrollbar::GraphicsScrollbar(int _initialHeight, QWidget* _parent)
|
||||
m_histogramItem->hide();
|
||||
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
this, &This::onExpectedFrameTimeChanged);
|
||||
this, &This::repaintHistogramImage);
|
||||
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::autoAdjustHistogramChanged,
|
||||
this, &This::onAutoAdjustHistogramChanged);
|
||||
@ -1187,6 +1613,15 @@ GraphicsScrollbar::~GraphicsScrollbar()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GraphicsScrollbar::repaintHistogramImage()
|
||||
{
|
||||
if (m_histogramItem->isVisible())
|
||||
{
|
||||
m_histogramItem->updateImage();
|
||||
scene()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScrollbar::onThreadViewChanged()
|
||||
{
|
||||
if (m_histogramItem->isVisible())
|
||||
@ -1196,15 +1631,6 @@ void GraphicsScrollbar::onThreadViewChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScrollbar::onExpectedFrameTimeChanged()
|
||||
{
|
||||
if (m_histogramItem->isVisible())
|
||||
{
|
||||
m_histogramItem->updateImage();
|
||||
scene()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScrollbar::onAutoAdjustHistogramChanged()
|
||||
{
|
||||
if (m_histogramItem->isVisible())
|
||||
@ -1225,7 +1651,7 @@ void GraphicsScrollbar::clear()
|
||||
Parent::clear();
|
||||
}
|
||||
|
||||
profiler::thread_id_t GraphicsScrollbar::hystThread() const
|
||||
profiler::thread_id_t GraphicsScrollbar::histThread() const
|
||||
{
|
||||
return m_histogramItem->threadId();
|
||||
}
|
||||
|
@ -80,12 +80,21 @@ private:
|
||||
profiler::timestamp_t m_blockTotalDuraion;
|
||||
QString m_topDurationStr;
|
||||
QString m_bottomDurationStr;
|
||||
QString m_medianDurationStr;
|
||||
QString m_avgDurationStr;
|
||||
QString m_threadName;
|
||||
QString m_blockName;
|
||||
QString m_blockType;
|
||||
profiler::BlocksTree::children_t m_selectedBlocks;
|
||||
profiler::timestamp_t m_threadDuration;
|
||||
profiler::timestamp_t m_threadProfiledTime;
|
||||
profiler::timestamp_t m_threadWaitTime;
|
||||
profiler::timestamp_t m_medianDuration;
|
||||
profiler::timestamp_t m_avgDuration;
|
||||
profiler::timestamp_t m_medianDurationFull;
|
||||
profiler::timestamp_t m_avgDurationFull;
|
||||
profiler::timestamp_t m_workerMedianDuration;
|
||||
profiler::timestamp_t m_workerAvgDuration;
|
||||
const profiler_gui::EasyItems* m_pSource;
|
||||
const profiler::BlocksTreeRoot* m_pProfilerThread;
|
||||
profiler::thread_id_t m_threadId;
|
||||
@ -136,7 +145,7 @@ private:
|
||||
void updateImageAsync(QRectF _boundingRect, HistRegime _regime, qreal _current_scale,
|
||||
qreal _minimum, qreal _maximum, qreal _range,
|
||||
qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, bool _bindMode,
|
||||
float _frame_time, profiler::timestamp_t _begin_time, bool _autoAdjustHist);
|
||||
float _frame_time, profiler::timestamp_t _begin_time, bool _autoAdjustHist, bool _drawBorders);
|
||||
|
||||
}; // END of class GraphicsHistogramItem.
|
||||
|
||||
@ -165,7 +174,7 @@ public:
|
||||
|
||||
// Public non-virtual methods
|
||||
|
||||
profiler::thread_id_t hystThread() const;
|
||||
profiler::thread_id_t histThread() const;
|
||||
|
||||
void setHistogramSource(profiler::thread_id_t _thread_id, const profiler_gui::EasyItems* _items);
|
||||
void setHistogramSource(profiler::thread_id_t _thread_id, profiler::block_id_t _block_id);
|
||||
@ -173,10 +182,13 @@ public:
|
||||
setHistogramSource(_thread_id, &_items);
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void repaintHistogramImage();
|
||||
|
||||
private slots:
|
||||
|
||||
void onThreadViewChanged();
|
||||
void onExpectedFrameTimeChanged();
|
||||
void onAutoAdjustHistogramChanged();
|
||||
void onDisplayOnlyFramesOnHistogramChanged();
|
||||
|
||||
|
@ -360,10 +360,10 @@ int GraphicsSliderArea::margins() const
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GraphicsSliderArea::setValue(qreal _value)
|
||||
bool GraphicsSliderArea::setValue(qreal _value)
|
||||
{
|
||||
if (m_bUpdatingPos)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const profiler_gui::BoolFlagGuard guard(m_bUpdatingPos, true);
|
||||
|
||||
@ -371,7 +371,7 @@ void GraphicsSliderArea::setValue(qreal _value)
|
||||
if (fabs(m_value - newValue) < 2 * std::numeric_limits<decltype(m_value)>::epsilon())
|
||||
{
|
||||
m_slider->setX(m_value + m_slider->halfwidth());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_value = newValue;
|
||||
@ -384,6 +384,8 @@ void GraphicsSliderArea::setValue(qreal _value)
|
||||
|
||||
if (m_imageItem->isVisible())
|
||||
m_imageItem->onValueChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsSliderArea::setRange(qreal _minValue, qreal _maxValue)
|
||||
@ -413,7 +415,11 @@ void GraphicsSliderArea::setRange(qreal _minValue, qreal _maxValue)
|
||||
void GraphicsSliderArea::setSliderWidth(qreal _width)
|
||||
{
|
||||
m_slider->setWidth(_width);
|
||||
setValue(m_value);
|
||||
if (!setValue(m_value))
|
||||
{
|
||||
if (m_imageItem->isVisible())
|
||||
m_imageItem->onValueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
int margin() const;
|
||||
int margins() const;
|
||||
|
||||
void setValue(qreal _value);
|
||||
bool setValue(qreal _value);
|
||||
void setRange(qreal _minValue, qreal _maxValue);
|
||||
void setSliderWidth(qreal _width);
|
||||
void setSelectionPos(qreal _left, qreal _right);
|
||||
|
@ -518,11 +518,24 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
menu->addSeparator();
|
||||
auto submenu = menu->addMenu("View");
|
||||
submenu->setToolTipsVisible(true);
|
||||
action = submenu->addAction("Draw borders");
|
||||
|
||||
action = submenu->addAction("Diagram borders");
|
||||
action->setToolTip("Draw borders for blocks on diagram.\nThis slightly reduces performance.");
|
||||
action->setCheckable(true);
|
||||
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
|
||||
connect(action, &QAction::triggered, [this](bool _checked){ EASY_GLOBALS.draw_graphics_items_borders = _checked; refreshDiagram(); });
|
||||
connect(action, &QAction::triggered, [this] (bool _checked) {
|
||||
EASY_GLOBALS.draw_graphics_items_borders = _checked;
|
||||
refreshDiagram();
|
||||
});
|
||||
|
||||
action = submenu->addAction("Histogram borders");
|
||||
action->setToolTip("Draw borders for histogram columns.");
|
||||
action->setCheckable(true);
|
||||
action->setChecked(EASY_GLOBALS.draw_histogram_borders);
|
||||
connect(action, &QAction::triggered, [this] (bool _checked) {
|
||||
EASY_GLOBALS.draw_histogram_borders = _checked;
|
||||
refreshHistogramImage();
|
||||
});
|
||||
|
||||
action = submenu->addAction("Overlap narrow children");
|
||||
action->setToolTip("Children blocks will be overlaped by narrow\nparent blocks. See also \'Blocks narrow size\'.\nThis improves performance.");
|
||||
@ -929,12 +942,13 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
toolbar->addWidget(lbl);
|
||||
|
||||
m_frameTimeEdit = new QLineEdit();
|
||||
m_frameTimeEdit->setFixedWidth(px(70));
|
||||
m_frameTimeEdit->setFixedWidth(px(80));
|
||||
auto val = new QDoubleValidator(m_frameTimeEdit);
|
||||
val->setLocale(QLocale::c());
|
||||
val->setBottom(0);
|
||||
val->setDecimals(3);
|
||||
m_frameTimeEdit->setValidator(val);
|
||||
m_frameTimeEdit->setText(QString::number(EASY_GLOBALS.frame_time * 1e-3));
|
||||
m_frameTimeEdit->setText(QString::number(EASY_GLOBALS.frame_time * 1e-3, 'f', 3));
|
||||
connect(m_frameTimeEdit, &QLineEdit::editingFinished, this, &This::onFrameTimeEditFinish);
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged, this, &This::onFrameTimeChanged);
|
||||
toolbar->addWidget(m_frameTimeEdit);
|
||||
@ -1349,6 +1363,11 @@ void MainWindow::refreshDiagram()
|
||||
static_cast<DiagramWidget*>(m_graphicsView->widget())->view()->scene()->update();
|
||||
}
|
||||
|
||||
void MainWindow::refreshHistogramImage()
|
||||
{
|
||||
static_cast<DiagramWidget*>(m_graphicsView->widget())->view()->repaintHistogramImage();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MainWindow::onDeleteClicked(bool)
|
||||
@ -1579,7 +1598,7 @@ void MainWindow::validateLineEdits()
|
||||
{
|
||||
m_addressEdit->setFixedWidth((m_addressEdit->fontMetrics().width(QString("255.255.255.255")) * 3) / 2);
|
||||
m_portEdit->setFixedWidth(m_portEdit->fontMetrics().width(QString("000000")) + 10);
|
||||
m_frameTimeEdit->setFixedWidth(m_frameTimeEdit->fontMetrics().width(QString("000000")));
|
||||
m_frameTimeEdit->setFixedWidth(m_frameTimeEdit->fontMetrics().width(QString("000.000")) + 5);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -1723,6 +1742,10 @@ void MainWindow::loadSettings()
|
||||
if (!flag.isNull())
|
||||
EASY_GLOBALS.draw_graphics_items_borders = flag.toBool();
|
||||
|
||||
flag = settings.value("draw_histogram_borders");
|
||||
if (!flag.isNull())
|
||||
EASY_GLOBALS.draw_histogram_borders = flag.toBool();
|
||||
|
||||
flag = settings.value("hide_narrow_children");
|
||||
if (!flag.isNull())
|
||||
EASY_GLOBALS.hide_narrow_children = flag.toBool();
|
||||
@ -1888,6 +1911,7 @@ void MainWindow::saveSettingsAndGeometry()
|
||||
settings.setValue("blocks_size_min", EASY_GLOBALS.blocks_size_min);
|
||||
settings.setValue("blocks_narrow_size", EASY_GLOBALS.blocks_narrow_size);
|
||||
settings.setValue("draw_graphics_items_borders", EASY_GLOBALS.draw_graphics_items_borders);
|
||||
settings.setValue("draw_histogram_borders", EASY_GLOBALS.draw_histogram_borders);
|
||||
settings.setValue("hide_narrow_children", EASY_GLOBALS.hide_narrow_children);
|
||||
settings.setValue("hide_minsize_blocks", EASY_GLOBALS.hide_minsize_blocks);
|
||||
settings.setValue("collapse_items_on_tree_close", EASY_GLOBALS.collapse_items_on_tree_close);
|
||||
@ -2571,19 +2595,12 @@ void MainWindow::onFrameTimeEditFinish()
|
||||
}
|
||||
|
||||
EASY_GLOBALS.frame_time = text.toFloat() * 1e3f;
|
||||
|
||||
disconnect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
this, &This::onFrameTimeChanged);
|
||||
|
||||
emit EASY_GLOBALS.events.expectedFrameTimeChanged();
|
||||
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
this, &This::onFrameTimeChanged);
|
||||
}
|
||||
|
||||
void MainWindow::onFrameTimeChanged()
|
||||
{
|
||||
m_frameTimeEdit->setText(QString::number(EASY_GLOBALS.frame_time * 1e-3));
|
||||
m_frameTimeEdit->setText(QString::number(EASY_GLOBALS.frame_time * 1e-3, 'f', 3));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -393,6 +393,7 @@ private:
|
||||
void clear();
|
||||
|
||||
void refreshDiagram();
|
||||
void refreshHistogramImage();
|
||||
|
||||
void addFileToList(const QString& filename, bool changeWindowTitle = true);
|
||||
void loadFile(const QString& filename);
|
||||
|
@ -89,7 +89,7 @@ struct ThreadData
|
||||
|
||||
using ThreadDataMap = std::unordered_map<profiler::thread_id_t, ThreadData, estd::hash<profiler::thread_id_t> >;
|
||||
|
||||
void calculate_medians(StatsMap::iterator begin, StatsMap::iterator end)
|
||||
void calculateMedians(StatsMap::iterator begin, StatsMap::iterator end)
|
||||
{
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
@ -99,65 +99,7 @@ void calculate_medians(StatsMap::iterator begin, StatsMap::iterator end)
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t total_count = 0;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
total_count += kv.second.count;
|
||||
}
|
||||
|
||||
auto& stats = it->second.stats;
|
||||
if (total_count & 1)
|
||||
{
|
||||
const auto index = total_count >> 1;
|
||||
size_t i = 0;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
const auto count = kv.second.count;
|
||||
|
||||
i += count;
|
||||
if (i < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stats.median_duration = kv.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto index2 = total_count >> 1;
|
||||
const auto index1 = index2 - 1;
|
||||
|
||||
size_t i = 0;
|
||||
bool i1 = false;
|
||||
for (auto& kv : durations)
|
||||
{
|
||||
const auto count = kv.second.count;
|
||||
|
||||
i += count;
|
||||
if (i < index1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!i1)
|
||||
{
|
||||
i1 = true;
|
||||
stats.median_duration = kv.first;
|
||||
}
|
||||
|
||||
if (i < index2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stats.median_duration += kv.first;
|
||||
stats.median_duration >>= 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
it->second.stats.median_duration = profiler_gui::calculateMedian(durations);
|
||||
|
||||
decltype(it->second.durations) dummy;
|
||||
dummy.swap(durations);
|
||||
@ -502,29 +444,16 @@ void TreeWidgetLoader::setTreeInternalTop(
|
||||
|
||||
if (total_count > _maxCount)
|
||||
{
|
||||
if (_maxCount > 10000)
|
||||
{
|
||||
m_error = QString(
|
||||
"Exceeded maximum rows count = %1k.\n"
|
||||
"Actual rows count: %2k (%3%).\n"
|
||||
"Please, reduce selected area width\n"
|
||||
"or increase maximum count in settings\n"
|
||||
"or change the tree mode."
|
||||
).arg(_maxCount / 1000).arg(total_count / 1000).arg(profiler_gui::percent(total_count, _maxCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_error = QString(
|
||||
"Exceeded maximum rows count = %1.\n"
|
||||
"Actual rows count: %2 (%3%).\n"
|
||||
"Please, reduce selected area width\n"
|
||||
"or increase maximum count in settings\n"
|
||||
"or change the tree mode."
|
||||
).arg(_maxCount).arg(total_count).arg(profiler_gui::percent(total_count, _maxCount));
|
||||
}
|
||||
|
||||
m_error = QString(
|
||||
"Exceeded maximum rows count = %1.\n"
|
||||
"Actual rows count: %2 (%3%).\n"
|
||||
"Please, reduce selected area width\n"
|
||||
"or increase maximum count in settings\n"
|
||||
"or change the tree mode."
|
||||
).arg(profiler_gui::shortenCountString(_maxCount))
|
||||
.arg(profiler_gui::shortenCountString(total_count))
|
||||
.arg(profiler_gui::percent(total_count, _maxCount));
|
||||
setDone();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1879,7 +1808,7 @@ void TreeWidgetLoader::fillStatsForTree(TreeWidgetItem* root, StatsMap& stats, p
|
||||
return;
|
||||
}
|
||||
|
||||
calculate_medians(stats.begin(), stats.end());
|
||||
calculateMedians(stats.begin(), stats.end());
|
||||
|
||||
std::deque<TreeWidgetItem*> queue;
|
||||
|
||||
|
@ -72,10 +72,8 @@ namespace loader {
|
||||
|
||||
struct Stats
|
||||
{
|
||||
struct Counter { uint32_t count = 0; };
|
||||
|
||||
profiler::BlockStatistics stats;
|
||||
std::map<profiler::timestamp_t, Counter> durations;
|
||||
profiler_gui::DurationsCountMap durations;
|
||||
|
||||
Stats(profiler::timestamp_t duration, profiler::block_index_t block_index, profiler::block_index_t parent_index)
|
||||
: stats(duration, block_index, parent_index)
|
||||
|
Loading…
x
Reference in New Issue
Block a user