mirror of
https://github.com/yse/easy_profiler.git
synced 2025-01-14 00:27:55 +08:00
(profiler GUI) high memory consumption optimizations: ~20 bytes per block
This commit is contained in:
parent
6df717781a
commit
24f181c040
@ -30,6 +30,7 @@
|
||||
#include <QScrollBar>
|
||||
#include <QGridLayout>
|
||||
#include <QFontMetrics>
|
||||
#include <QDebug>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include "blocks_graphics_view.h"
|
||||
@ -48,8 +49,9 @@ const qreal MAX_SCALE = pow(SCALING_COEFFICIENT, 30); // ~800
|
||||
const qreal BASE_SCALE = pow(SCALING_COEFFICIENT_INV, 25); // ~0.003
|
||||
|
||||
const unsigned short GRAPHICS_ROW_SIZE = 16;
|
||||
const unsigned short GRAPHICS_ROW_SIZE_FULL = GRAPHICS_ROW_SIZE + 2;
|
||||
const unsigned short ROW_SPACING = 4;
|
||||
const unsigned short GRAPHICS_ROW_SPACING = 2;
|
||||
const unsigned short GRAPHICS_ROW_SIZE_FULL = GRAPHICS_ROW_SIZE + GRAPHICS_ROW_SPACING;
|
||||
const unsigned short THREADS_ROW_SPACING = 4;
|
||||
|
||||
const QRgb BORDERS_COLOR = 0x00a07050;
|
||||
const QRgb BACKGROUND_1 = 0x00dddddd;
|
||||
@ -79,15 +81,11 @@ inline T logn(T _value)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProfGraphicsItem::ProfGraphicsItem() : ProfGraphicsItem(false)
|
||||
ProfGraphicsItem::ProfGraphicsItem(unsigned char _index, bool _test) : QGraphicsItem(nullptr), m_bTest(_test), m_pRoot(nullptr), m_index(_index)
|
||||
{
|
||||
}
|
||||
|
||||
ProfGraphicsItem::ProfGraphicsItem(bool _test) : QGraphicsItem(nullptr), m_bTest(_test), m_pRoot(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ProfGraphicsItem::ProfGraphicsItem(const ::profiler::BlocksTreeRoot* _root) : ProfGraphicsItem(false)
|
||||
ProfGraphicsItem::ProfGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root) : ProfGraphicsItem(_index, false)
|
||||
{
|
||||
m_pRoot = _root;
|
||||
}
|
||||
@ -138,8 +136,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
|
||||
// Reset indices of first visible item for each layer
|
||||
const auto levelsNumber = levels();
|
||||
for (unsigned short i = 1; i < levelsNumber; ++i)
|
||||
m_levelsIndexes[i] = -1;
|
||||
for (unsigned char i = 1; i < levelsNumber; ++i) ::profiler_gui::set_max(m_levelsIndexes[i]);
|
||||
|
||||
|
||||
// Search for first visible top-level item
|
||||
@ -185,23 +182,25 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
|
||||
// Iterate through layers and draw visible items
|
||||
bool selectedItemsWasPainted = false;
|
||||
for (unsigned short l = 0; l < levelsNumber; ++l)
|
||||
for (unsigned char l = 0; l < levelsNumber; ++l)
|
||||
{
|
||||
auto& level = m_levels[l];
|
||||
const auto next_level = l + 1;
|
||||
const short next_level = l + 1;
|
||||
char state = 1;
|
||||
//bool changebrush = false;
|
||||
|
||||
const auto top = levelY(l);
|
||||
for (unsigned int i = m_levelsIndexes[l], end = static_cast<unsigned int>(level.size()); i < end; ++i)
|
||||
{
|
||||
auto& item = level[i];
|
||||
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max(item.children_begin);
|
||||
|
||||
if (item.state != 0)
|
||||
{
|
||||
state = item.state;
|
||||
}
|
||||
|
||||
if (item.right() < sceneLeft || state == -1 || (l == 0 && (item.top() > visibleSceneRect.bottom() || (item.top() + item.totalHeight) < visibleSceneRect.top())))
|
||||
if (item.right() < sceneLeft || state == -1 || (l == 0 && (top > visibleSceneRect.bottom() || (top + item.totalHeight) < visibleSceneRect.top())))
|
||||
{
|
||||
// This item is not visible
|
||||
++m_levelsIndexes[l];
|
||||
@ -275,7 +274,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
}
|
||||
|
||||
// Draw rectangle
|
||||
rect.setRect(x, item.top(), w, item.totalHeight);
|
||||
rect.setRect(x, top, w, item.totalHeight);
|
||||
_painter->drawRect(rect);
|
||||
|
||||
if (changepen)
|
||||
@ -286,7 +285,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
_painter->setPen(BORDERS_COLOR); // restore pen for rectangle painting
|
||||
}
|
||||
|
||||
if (next_level < levelsNumber && item.children_begin != NEGATIVE_ONE)
|
||||
if (next_level < levelsNumber && item.children_begin != MAX_CHILD_INDEX)
|
||||
{
|
||||
// Mark that we would not paint children of current item
|
||||
m_levels[next_level][item.children_begin].state = -1;
|
||||
@ -295,9 +294,9 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next_level < levelsNumber && item.children_begin != NEGATIVE_ONE)
|
||||
if (next_level < levelsNumber && item.children_begin != MAX_CHILD_INDEX)
|
||||
{
|
||||
if (m_levelsIndexes[next_level] == NEGATIVE_ONE)
|
||||
if (m_levelsIndexes[next_level] == MAX_CHILD_INDEX)
|
||||
{
|
||||
// Mark first potentially visible child item on next sublevel
|
||||
m_levelsIndexes[next_level] = item.children_begin;
|
||||
@ -353,7 +352,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
|
||||
// Draw rectangle
|
||||
const auto x = item.left() * currentScale - dx;
|
||||
rect.setRect(x, item.top(), w, item.height());
|
||||
rect.setRect(x, top, w, GRAPHICS_ROW_SIZE);
|
||||
_painter->drawRect(rect);
|
||||
|
||||
// Draw text-----------------------------------
|
||||
@ -367,7 +366,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
xtext = sceneLeft * currentScale - dx;
|
||||
}
|
||||
|
||||
rect.setRect(xtext + 1, item.top(), w - 1, item.height());
|
||||
rect.setRect(xtext + 1, top, w - 1, GRAPHICS_ROW_SIZE);
|
||||
|
||||
// text will be painted with inverse color
|
||||
auto textColor = 0x00ffffff - previousColor;
|
||||
@ -399,7 +398,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
if (!selectedItemsWasPainted && !m_bTest && ::profiler_gui::EASY_GLOBALS.selected_block < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
|
||||
{
|
||||
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[::profiler_gui::EASY_GLOBALS.selected_block];
|
||||
if (guiblock.graphics_item == this)
|
||||
if (guiblock.graphics_item == m_index)
|
||||
{
|
||||
const auto& item = m_levels[guiblock.graphics_item_level][guiblock.graphics_item_index];
|
||||
if (item.left() < sceneRight && item.right() > sceneLeft)
|
||||
@ -412,7 +411,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
|
||||
brush.setColor(previousColor);
|
||||
_painter->setBrush(brush);
|
||||
|
||||
rect.setRect(item.left() * currentScale - dx, item.top(), ::std::max(item.width() * currentScale, 1.0), item.totalHeight);
|
||||
rect.setRect(item.left() * currentScale - dx, levelY(guiblock.graphics_item_level), ::std::max(item.width() * currentScale, 1.0), item.totalHeight);
|
||||
_painter->drawRect(rect);
|
||||
}
|
||||
}
|
||||
@ -486,7 +485,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
}
|
||||
|
||||
const auto& level0 = m_levels.front();
|
||||
const auto top = level0.front().top();
|
||||
const auto top = y();
|
||||
|
||||
if (top > _pos.y())
|
||||
{
|
||||
@ -507,7 +506,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
|
||||
const auto currentScale = view()->scale();
|
||||
unsigned int i = 0;
|
||||
size_t itemIndex = -1;
|
||||
size_t itemIndex = ::std::numeric_limits<size_t>::max();
|
||||
size_t firstItem = 0, lastItem = static_cast<unsigned int>(level0.size());
|
||||
while (i <= levelIndex)
|
||||
{
|
||||
@ -533,6 +532,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
for (auto size = level.size(); itemIndex < size; ++itemIndex)
|
||||
{
|
||||
const auto& item = level[itemIndex];
|
||||
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max(item.children_begin);
|
||||
|
||||
if (item.left() > _pos.x())
|
||||
{
|
||||
@ -550,7 +550,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
return &item;
|
||||
}
|
||||
|
||||
if (item.children_begin == NEGATIVE_ONE)
|
||||
if (item.children_begin == MAX_CHILD_INDEX)
|
||||
{
|
||||
if (itemIndex != 0)
|
||||
{
|
||||
@ -560,7 +560,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
|
||||
--j;
|
||||
const auto& item2 = level[j];
|
||||
if (item2.children_begin != NEGATIVE_ONE)
|
||||
if (item2.children_begin != MAX_CHILD_INDEX)
|
||||
{
|
||||
firstItem = item2.children_begin;
|
||||
break;
|
||||
@ -582,7 +582,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
|
||||
for (auto j = itemIndex + 1; j < size; ++j)
|
||||
{
|
||||
const auto& item2 = level[j];
|
||||
if (item2.children_begin != NEGATIVE_ONE)
|
||||
if (item2.children_begin != MAX_CHILD_INDEX)
|
||||
{
|
||||
lastItem = item2.children_begin;
|
||||
break;
|
||||
@ -619,40 +619,48 @@ void ProfGraphicsItem::setBoundingRect(const QRectF& _rect)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned short ProfGraphicsItem::levels() const
|
||||
unsigned char ProfGraphicsItem::levels() const
|
||||
{
|
||||
return static_cast<unsigned short>(m_levels.size());
|
||||
return static_cast<unsigned char>(m_levels.size());
|
||||
}
|
||||
|
||||
void ProfGraphicsItem::setLevels(unsigned short _levels)
|
||||
float ProfGraphicsItem::levelY(unsigned char _level) const
|
||||
{
|
||||
return y() + static_cast<int>(_level) * static_cast<int>(GRAPHICS_ROW_SIZE_FULL);
|
||||
}
|
||||
|
||||
void ProfGraphicsItem::setLevels(unsigned char _levels)
|
||||
{
|
||||
typedef decltype(m_levelsIndexes) IndexesT;
|
||||
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max<IndexesT::value_type>();
|
||||
|
||||
m_levels.resize(_levels);
|
||||
m_levelsIndexes.resize(_levels, -1);
|
||||
m_levelsIndexes.resize(_levels, MAX_CHILD_INDEX);
|
||||
}
|
||||
|
||||
void ProfGraphicsItem::reserve(unsigned short _level, unsigned int _items)
|
||||
void ProfGraphicsItem::reserve(unsigned char _level, unsigned int _items)
|
||||
{
|
||||
m_levels[_level].reserve(_items);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const ProfGraphicsItem::Children& ProfGraphicsItem::items(unsigned short _level) const
|
||||
const ProfGraphicsItem::Children& ProfGraphicsItem::items(unsigned char _level) const
|
||||
{
|
||||
return m_levels[_level];
|
||||
}
|
||||
|
||||
const ::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index) const
|
||||
const ::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned char _level, unsigned int _index) const
|
||||
{
|
||||
return m_levels[_level][_index];
|
||||
}
|
||||
|
||||
::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index)
|
||||
::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned char _level, unsigned int _index)
|
||||
{
|
||||
return m_levels[_level][_index];
|
||||
}
|
||||
|
||||
unsigned int ProfGraphicsItem::addItem(unsigned short _level)
|
||||
unsigned int ProfGraphicsItem::addItem(unsigned char _level)
|
||||
{
|
||||
m_levels[_level].emplace_back();
|
||||
return static_cast<unsigned int>(m_levels[_level].size() - 1);
|
||||
@ -875,7 +883,7 @@ void ProfBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte
|
||||
const auto& items = sceneView->getItems();
|
||||
if (!items.empty())
|
||||
{
|
||||
static const auto OVERLAP = ROW_SPACING >> 1;
|
||||
static const auto OVERLAP = THREADS_ROW_SPACING >> 1;
|
||||
static const QBrush brushes[2] = {QColor::fromRgb(BACKGROUND_1), QColor::fromRgb(BACKGROUND_2)};
|
||||
const bool isTest = (items.front()->items(0).front().block == nullptr);
|
||||
int i = -1;
|
||||
@ -961,7 +969,7 @@ void ProfTimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGrap
|
||||
|
||||
ProfGraphicsView::ProfGraphicsView(QWidget* _parent)
|
||||
: QGraphicsView(_parent)
|
||||
, m_beginTime(-1)
|
||||
, m_beginTime(::std::numeric_limits<decltype(m_beginTime)>::max())
|
||||
, m_scale(1)
|
||||
, m_offset(0)
|
||||
, m_mouseButtons(Qt::NoButton)
|
||||
@ -999,7 +1007,7 @@ ProfChronometerItem* ProfGraphicsView::createChronometer(bool _main)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, qreal _y, unsigned int _childrenNumber, unsigned int& _total_items)
|
||||
void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, unsigned int _childrenNumber, unsigned int& _total_items)
|
||||
{
|
||||
unsigned int nchildren = _childrenNumber;
|
||||
_childrenNumber = TEST_PROGRESSION_BASE;
|
||||
@ -1016,17 +1024,17 @@ void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxl
|
||||
const auto& children = _item->items(_level + 1);
|
||||
b.children_begin = static_cast<unsigned int>(children.size());
|
||||
|
||||
fillTestChildren(_item, _maxlevel, _level + 1, _x, _y + GRAPHICS_ROW_SIZE_FULL, _childrenNumber, _total_items);
|
||||
fillTestChildren(_item, _maxlevel, _level + 1, _x, _childrenNumber, _total_items);
|
||||
|
||||
const auto& last = children.back();
|
||||
b.setRect(_x, _y, last.right() - _x, GRAPHICS_ROW_SIZE);
|
||||
b.setPos(_x, last.right() - _x);
|
||||
b.totalHeight = GRAPHICS_ROW_SIZE_FULL + last.totalHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
b.setRect(_x, _y, units2microseconds(10 + rand() % 190), GRAPHICS_ROW_SIZE);
|
||||
b.setPos(_x, units2microseconds(10 + rand() % 190));
|
||||
b.totalHeight = GRAPHICS_ROW_SIZE;
|
||||
b.children_begin = -1;
|
||||
::profiler_gui::set_max(b.children_begin);
|
||||
}
|
||||
|
||||
_x = b.right();
|
||||
@ -1034,7 +1042,7 @@ void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxl
|
||||
}
|
||||
}
|
||||
|
||||
void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_items_number_estimate, int _rows)
|
||||
void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_items_number_estimate, unsigned char _rows)
|
||||
{
|
||||
static const qreal X_BEGIN = 50;
|
||||
static const qreal Y_BEGIN = 0;
|
||||
@ -1042,9 +1050,9 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
|
||||
clearSilent(); // Clear scene
|
||||
|
||||
// Calculate items number for first level
|
||||
_rows = ::std::max(1, _rows);
|
||||
_rows = ::std::max((unsigned char)1, _rows);
|
||||
const auto children_per_frame = static_cast<unsigned int>(0.5 + static_cast<double>(_total_items_number_estimate) / static_cast<double>(_rows * _frames_number));
|
||||
const int max_depth = logn<TEST_PROGRESSION_BASE>(children_per_frame * (TEST_PROGRESSION_BASE - 1) * 0.5 + 1);
|
||||
const unsigned char max_depth = ::std::min(254, static_cast<int>(logn<TEST_PROGRESSION_BASE>(children_per_frame * (TEST_PROGRESSION_BASE - 1) * 0.5 + 1)));
|
||||
const auto first_level_children_count = static_cast<unsigned int>(static_cast<double>(children_per_frame) * (1.0 - TEST_PROGRESSION_BASE) / (1.0 - pow(TEST_PROGRESSION_BASE, max_depth)) + 0.5);
|
||||
|
||||
|
||||
@ -1053,12 +1061,12 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
|
||||
|
||||
|
||||
::std::vector<ProfGraphicsItem*> thread_items(_rows);
|
||||
for (int i = 0; i < _rows; ++i)
|
||||
for (unsigned char i = 0; i < _rows; ++i)
|
||||
{
|
||||
auto item = new ProfGraphicsItem(true);
|
||||
auto item = new ProfGraphicsItem(i, true);
|
||||
thread_items[i] = item;
|
||||
|
||||
item->setPos(0, Y_BEGIN + i * (max_depth * GRAPHICS_ROW_SIZE_FULL + ROW_SPACING * 5));
|
||||
item->setPos(0, Y_BEGIN + i * (max_depth * GRAPHICS_ROW_SIZE_FULL + THREADS_ROW_SPACING * 5));
|
||||
|
||||
item->setLevels(max_depth + 1);
|
||||
item->reserve(0, _frames_number);
|
||||
@ -1066,11 +1074,11 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
|
||||
|
||||
// Calculate items number for each sublevel
|
||||
auto chldrn = first_level_children_count;
|
||||
for (int i = 1; i <= max_depth; ++i)
|
||||
for (unsigned char i = 1; i <= max_depth; ++i)
|
||||
{
|
||||
for (int i = 0; i < _rows; ++i)
|
||||
for (unsigned char j = 0; j < _rows; ++j)
|
||||
{
|
||||
auto item = thread_items[i];
|
||||
auto item = thread_items[j];
|
||||
item->reserve(i, chldrn * _frames_number);
|
||||
}
|
||||
|
||||
@ -1081,11 +1089,11 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
|
||||
unsigned int total_items = 0;
|
||||
qreal maxX = 0;
|
||||
const ProfGraphicsItem* longestItem = nullptr;
|
||||
for (int i = 0; i < _rows; ++i)
|
||||
for (unsigned char i = 0; i < _rows; ++i)
|
||||
{
|
||||
auto item = thread_items[i];
|
||||
qreal x = X_BEGIN, y = item->y();
|
||||
for (unsigned int i = 0; i < _frames_number; ++i)
|
||||
for (unsigned int f = 0; f < _frames_number; ++f)
|
||||
{
|
||||
auto j = item->addItem(0);
|
||||
auto& b = item->getItem(0, j);
|
||||
@ -1095,10 +1103,10 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
|
||||
const auto& children = item->items(1);
|
||||
b.children_begin = static_cast<unsigned int>(children.size());
|
||||
|
||||
fillTestChildren(item, max_depth, 1, x, y + GRAPHICS_ROW_SIZE_FULL, first_level_children_count, total_items);
|
||||
fillTestChildren(item, max_depth, 1, x, first_level_children_count, total_items);
|
||||
|
||||
const auto& last = children.back();
|
||||
b.setRect(x, y, last.right() - x, GRAPHICS_ROW_SIZE);
|
||||
b.setPos(x, last.right() - x);
|
||||
b.totalHeight = GRAPHICS_ROW_SIZE_FULL + last.totalHeight;
|
||||
|
||||
x += b.width() * 1.2;
|
||||
@ -1170,7 +1178,7 @@ void ProfGraphicsView::clearSilent()
|
||||
m_items.clear();
|
||||
m_selectedBlocks.clear();
|
||||
|
||||
m_beginTime = -1; // reset begin time
|
||||
m_beginTime = ::std::numeric_limits<decltype(m_beginTime)>::max(); // reset begin time
|
||||
m_scale = 1; // scale back to initial 100% scale
|
||||
m_timelineStep = 1;
|
||||
m_offset = 0; // scroll back to the beginning of the scene
|
||||
@ -1229,7 +1237,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
|
||||
// fill scene with new items
|
||||
const auto& tree = threadTree.second.tree;
|
||||
qreal h = 0, x = time2position(tree.children.front().node->block()->getBegin());
|
||||
auto item = new ProfGraphicsItem(&threadTree.second);
|
||||
auto item = new ProfGraphicsItem(static_cast<unsigned char>(m_items.size()), &threadTree.second);
|
||||
item->setLevels(tree.depth);
|
||||
item->setPos(0, y);
|
||||
|
||||
@ -1239,12 +1247,18 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
|
||||
m_items.push_back(item);
|
||||
scene()->addItem(item);
|
||||
|
||||
y += h + ROW_SPACING;
|
||||
y += h + THREADS_ROW_SPACING;
|
||||
|
||||
if (longestTree == &tree)
|
||||
{
|
||||
longestItem = item;
|
||||
}
|
||||
|
||||
if (m_items.size() == 0xff)
|
||||
{
|
||||
qWarning() << "Maximum threads number (255 threads) exceeded! See ProfGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculating scene rect
|
||||
@ -1286,7 +1300,7 @@ const ProfGraphicsView::Items &ProfGraphicsView::getItems() const
|
||||
return m_items;
|
||||
}
|
||||
|
||||
qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, unsigned short _level)
|
||||
qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
|
||||
{
|
||||
static const qreal MIN_DURATION = 0.25;
|
||||
|
||||
@ -1295,9 +1309,11 @@ qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::Block
|
||||
return 0;
|
||||
}
|
||||
|
||||
_item->reserve(_level, static_cast<unsigned int>(_children.size()));
|
||||
const auto level = static_cast<unsigned char>(_level);
|
||||
_item->reserve(level, static_cast<unsigned int>(_children.size()));
|
||||
|
||||
const auto next_level = _level + 1;
|
||||
const short next_level = _level + 1;
|
||||
bool warned = false;
|
||||
qreal total_duration = 0, prev_end = 0, maxh = 0;
|
||||
qreal start_time = -1;
|
||||
for (const auto& child : _children)
|
||||
@ -1322,25 +1338,36 @@ qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::Block
|
||||
duration = MIN_DURATION;
|
||||
}
|
||||
|
||||
auto i = _item->addItem(_level);
|
||||
auto& b = _item->getItem(_level, i);
|
||||
auto i = _item->addItem(level);
|
||||
auto& b = _item->getItem(level, i);
|
||||
|
||||
auto& gui_block = ::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index];
|
||||
gui_block.graphics_item = _item;
|
||||
gui_block.graphics_item_level = _level;
|
||||
gui_block.graphics_item = _item->index();
|
||||
gui_block.graphics_item_level = level;
|
||||
gui_block.graphics_item_index = i;
|
||||
|
||||
if (next_level < _item->levels() && !child.children.empty())
|
||||
if (next_level < 256 && next_level < _item->levels() && !child.children.empty())
|
||||
{
|
||||
b.children_begin = static_cast<unsigned int>(_item->items(next_level).size());
|
||||
b.children_begin = static_cast<unsigned int>(_item->items(static_cast<unsigned char>(next_level)).size());
|
||||
}
|
||||
else
|
||||
{
|
||||
b.children_begin = -1;
|
||||
::profiler_gui::set_max(b.children_begin);
|
||||
}
|
||||
|
||||
qreal h = 0;
|
||||
const auto children_duration = setTree(_item, child.children, h, _y + GRAPHICS_ROW_SIZE_FULL, next_level);
|
||||
qreal children_duration = 0;
|
||||
|
||||
if (next_level < 256)
|
||||
{
|
||||
children_duration = setTree(_item, child.children, h, _y + GRAPHICS_ROW_SIZE_FULL, next_level);
|
||||
}
|
||||
else if (!child.children.empty() && !warned)
|
||||
{
|
||||
warned = true;
|
||||
qWarning() << "Maximum blocks depth (255) exceeded! See ProfGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
|
||||
}
|
||||
|
||||
if (duration < children_duration)
|
||||
{
|
||||
duration = children_duration;
|
||||
@ -1354,7 +1381,7 @@ qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::Block
|
||||
const auto color = child.node->block()->getColor();
|
||||
b.block = &child;
|
||||
b.color = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
|
||||
b.setRect(xbegin, _y, duration, GRAPHICS_ROW_SIZE);
|
||||
b.setPos(xbegin, duration);
|
||||
b.totalHeight = GRAPHICS_ROW_SIZE + h;
|
||||
|
||||
prev_end = xbegin + duration;
|
||||
@ -1411,7 +1438,7 @@ void ProfGraphicsView::updateTimelineStep(qreal _windowWidth)
|
||||
m_timelineStep = 1e6;
|
||||
|
||||
auto steps = time / m_timelineStep;
|
||||
while (steps > 50) {
|
||||
while (steps > 60) {
|
||||
m_timelineStep *= 10;
|
||||
steps *= 0.1;
|
||||
}
|
||||
@ -1877,12 +1904,13 @@ void ProfGraphicsView::onSelectedBlockChange(unsigned int _block_index)
|
||||
// Scroll to item
|
||||
|
||||
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index];
|
||||
const auto& item = guiblock.graphics_item->items(guiblock.graphics_item_level)[guiblock.graphics_item_index];
|
||||
const auto thread_item = m_items[guiblock.graphics_item];
|
||||
const auto& item = thread_item->items(guiblock.graphics_item_level)[guiblock.graphics_item_index];
|
||||
|
||||
m_flickerSpeedX = m_flickerSpeedY = 0;
|
||||
|
||||
m_bUpdatingRect = true;
|
||||
verticalScrollBar()->setValue(static_cast<int>(item.top() - m_visibleSceneRect.height() * 0.5));
|
||||
verticalScrollBar()->setValue(static_cast<int>(thread_item->levelY(guiblock.graphics_item_level) - m_visibleSceneRect.height() * 0.5));
|
||||
m_pScrollbar->setValue(item.left() + item.width() * 0.5 - m_pScrollbar->sliderHalfWidth());
|
||||
m_bUpdatingRect = false;
|
||||
}
|
||||
|
@ -70,12 +70,12 @@ class ProfGraphicsItem : public QGraphicsItem
|
||||
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem)
|
||||
const ::profiler::BlocksTreeRoot* m_pRoot; ///< Pointer to the root profiler block (thread block). Used by ProfTreeWidget to restore hierarchy.
|
||||
const bool m_bTest; ///< If true then we are running test()
|
||||
unsigned char m_index; ///< This item's index in the list of items of ProfGraphicsView
|
||||
|
||||
public:
|
||||
|
||||
ProfGraphicsItem();
|
||||
ProfGraphicsItem(bool _test);
|
||||
ProfGraphicsItem(const ::profiler::BlocksTreeRoot* _root);
|
||||
ProfGraphicsItem(unsigned char _index, bool _test);
|
||||
ProfGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root);
|
||||
virtual ~ProfGraphicsItem();
|
||||
|
||||
// Public virtual methods
|
||||
@ -96,44 +96,46 @@ public:
|
||||
::profiler::thread_id_t threadId() const;
|
||||
|
||||
///< Returns number of levels
|
||||
unsigned short levels() const;
|
||||
unsigned char levels() const;
|
||||
|
||||
float levelY(unsigned char _level) const;
|
||||
|
||||
/** \brief Sets number of levels.
|
||||
|
||||
\note Must be set before doing anything else.
|
||||
|
||||
\param _levels Desired number of levels */
|
||||
void setLevels(unsigned short _levels);
|
||||
void setLevels(unsigned char _levels);
|
||||
|
||||
/** \brief Reserves memory for desired number of items on specified level.
|
||||
|
||||
\param _level Index of the level
|
||||
\param _items Desired number of items on this level */
|
||||
void reserve(unsigned short _level, unsigned int _items);
|
||||
void reserve(unsigned char _level, unsigned int _items);
|
||||
|
||||
/**\brief Returns reference to the array of items of specified level.
|
||||
|
||||
\param _level Index of the level */
|
||||
const Children& items(unsigned short _level) const;
|
||||
const Children& items(unsigned char _level) const;
|
||||
|
||||
/**\brief Returns reference to the item with required index on specified level.
|
||||
|
||||
\param _level Index of the level
|
||||
\param _index Index of required item */
|
||||
const ::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index) const;
|
||||
const ::profiler_gui::ProfBlockItem& getItem(unsigned char _level, unsigned int _index) const;
|
||||
|
||||
/**\brief Returns reference to the item with required index on specified level.
|
||||
|
||||
\param _level Index of the level
|
||||
\param _index Index of required item */
|
||||
::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index);
|
||||
::profiler_gui::ProfBlockItem& getItem(unsigned char _level, unsigned int _index);
|
||||
|
||||
/** \brief Adds new item to required level.
|
||||
|
||||
\param _level Index of the level
|
||||
|
||||
\retval Index of the new created item */
|
||||
unsigned int addItem(unsigned short _level);
|
||||
unsigned int addItem(unsigned char _level);
|
||||
|
||||
/** \brief Finds top-level blocks which are intersects with required selection zone.
|
||||
|
||||
@ -151,6 +153,16 @@ private:
|
||||
///< Returns pointer to the ProfGraphicsView widget.
|
||||
const ProfGraphicsView* view() const;
|
||||
|
||||
public:
|
||||
|
||||
// Public inline methods
|
||||
|
||||
///< Returns this item's index in the list of graphics items of ProfGraphicsView
|
||||
inline unsigned char index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
}; // END of class ProfGraphicsItem.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -297,7 +309,7 @@ public:
|
||||
void setScrollbar(ProfGraphicsScrollbar* _scrollbar);
|
||||
void clearSilent();
|
||||
|
||||
void test(unsigned int _frames_number, unsigned int _total_items_number_estimate, int _rows);
|
||||
void test(unsigned int _frames_number, unsigned int _total_items_number_estimate, unsigned char _rows);
|
||||
void setTree(const ::profiler::thread_blocks_tree_t& _blocksTree);
|
||||
|
||||
const Items& getItems() const;
|
||||
@ -319,8 +331,8 @@ private:
|
||||
void updateTimelineStep(qreal _windowWidth);
|
||||
void updateScene();
|
||||
void scaleTo(qreal _scale);
|
||||
qreal setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, unsigned short _level);
|
||||
void fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, qreal _y, unsigned int _childrenNumber, unsigned int& _total_items);
|
||||
qreal setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level);
|
||||
void fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, unsigned int _childrenNumber, unsigned int& _total_items);
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -244,7 +244,7 @@ void ProfTreeWidgetItem::expandAll()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProfTreeWidget::ProfTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime(-1), m_bColorRows(true)
|
||||
ProfTreeWidget::ProfTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime(::std::numeric_limits<decltype(m_beginTime)>::max()), m_bColorRows(true)
|
||||
{
|
||||
setAutoFillBackground(false);
|
||||
setAlternatingRowColors(true);
|
||||
@ -339,7 +339,7 @@ void ProfTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, ::
|
||||
|
||||
void ProfTreeWidget::clearSilent(bool _global)
|
||||
{
|
||||
m_beginTime = -1;
|
||||
m_beginTime = ::std::numeric_limits<decltype(m_beginTime)>::max();
|
||||
|
||||
setSortingEnabled(false);
|
||||
disconnect(this, &Parent::itemExpanded, this, &This::onItemExpand);
|
||||
@ -348,7 +348,7 @@ void ProfTreeWidget::clearSilent(bool _global)
|
||||
{
|
||||
for (auto item : m_items)
|
||||
{
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].tree_item = nullptr;
|
||||
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].tree_item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ size_t ProfTreeWidget::setTreeInternal(const ::profiler_gui::TreeBlocks& _blocks
|
||||
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
|
||||
{
|
||||
total_items += children_items_number + 1;
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].tree_item = item;
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].tree_item = static_cast<unsigned int>(m_items.size() - 1);
|
||||
|
||||
if (m_bColorRows)
|
||||
{
|
||||
@ -770,7 +770,7 @@ size_t ProfTreeWidget::setTreeInternal(const ::profiler::BlocksTree::children_t&
|
||||
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
|
||||
{
|
||||
total_items += children_items_number + 1;
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].tree_item = item;
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].tree_item = static_cast<unsigned int>(m_items.size() - 1);
|
||||
|
||||
if (m_bColorRows)
|
||||
{
|
||||
@ -842,7 +842,7 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
|
||||
case COL_MAX_PER_PARENT:
|
||||
case COL_MAX_PER_FRAME:
|
||||
{
|
||||
unsigned int i = NEGATIVE_ONE;
|
||||
auto i = ::profiler_gui::numeric_max<unsigned int>();
|
||||
switch (col)
|
||||
{
|
||||
case COL_MIN_PER_THREAD: i = item->block()->per_thread_stats->min_duration_block; break;
|
||||
@ -853,7 +853,7 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
|
||||
case COL_MAX_PER_FRAME: i = item->block()->per_frame_stats->max_duration_block; break;
|
||||
}
|
||||
|
||||
if (i != NEGATIVE_ONE)
|
||||
if (i != ::profiler_gui::numeric_max(i))
|
||||
{
|
||||
menu.addSeparator();
|
||||
itemAction = new ProfItemAction("Jump to such item", i);
|
||||
@ -973,17 +973,18 @@ void ProfTreeWidget::onSelectedThreadChange(::profiler::thread_id_t _id)
|
||||
|
||||
void ProfTreeWidget::onSelectedBlockChange(unsigned int _block_index)
|
||||
{
|
||||
ProfTreeWidgetItem* item = nullptr;
|
||||
|
||||
if (_block_index < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
|
||||
{
|
||||
auto item = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index].tree_item;
|
||||
if (item != nullptr)
|
||||
scrollToItem(item, QAbstractItemView::PositionAtCenter);
|
||||
setCurrentItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
setCurrentItem(nullptr);
|
||||
const auto i = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index].tree_item;
|
||||
if (i < m_items.size())
|
||||
item = m_items[i];
|
||||
}
|
||||
|
||||
if (item != nullptr)
|
||||
scrollToItem(item, QAbstractItemView::PositionAtCenter);
|
||||
setCurrentItem(item);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -110,26 +110,20 @@ struct ProfBlockItem final
|
||||
const ::profiler::BlocksTree* block; ///< Pointer to profiler block
|
||||
qreal x; ///< x coordinate of the item (this is made qreal=double to avoid mistakes on very wide scene)
|
||||
float w; ///< Width of the item
|
||||
float y; ///< y coordinate of the item
|
||||
float h; ///< Height of the item
|
||||
QRgb color; ///< Background color of the item
|
||||
unsigned int children_begin; ///< Index of first child item on the next sublevel
|
||||
unsigned short totalHeight; ///< Total height of the item including heights of all it's children
|
||||
char state; ///< 0 = no change, 1 = paint, -1 = do not paint
|
||||
|
||||
inline void setRect(qreal _x, float _y, float _w, float _h) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
w = _w;
|
||||
h = _h;
|
||||
}
|
||||
// Possible optimizations:
|
||||
// 1) We can save 1 more byte per block if we will use char instead of short + real time calculations for "totalHeight" var;
|
||||
// 2) We can save 12 bytes per block if "x" and "w" vars will be removed (all this information exist inside BlocksTree),
|
||||
// but this will make impossible to run graphics test without loading any .prof file.
|
||||
|
||||
inline void setPos(qreal _x, float _w) { x = _x; w = _w; }
|
||||
inline qreal left() const { return x; }
|
||||
inline float top() const { return y; }
|
||||
inline float width() const { return w; }
|
||||
inline float height() const { return h; }
|
||||
inline qreal right() const { return x + w; }
|
||||
inline float bottom() const { return y + h; }
|
||||
inline float width() const { return w; }
|
||||
|
||||
}; // END of struct ProfBlockItem.
|
||||
#pragma pack(pop)
|
||||
@ -191,6 +185,20 @@ inline QString timeStringInt(qreal _interval)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> inline T numeric_max() {
|
||||
return ::std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <class T> inline T numeric_max(T) {
|
||||
return ::std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <class T> inline void set_max(T& _value) {
|
||||
_value = ::std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // END of namespace profiler_gui.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -31,8 +31,6 @@
|
||||
class ProfGraphicsItem;
|
||||
class ProfTreeWidgetItem;
|
||||
|
||||
const unsigned int NEGATIVE_ONE = std::numeric_limits<unsigned int>::max();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace profiler_gui {
|
||||
@ -46,13 +44,15 @@ namespace profiler_gui {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ProfBlock final
|
||||
{
|
||||
ProfGraphicsItem* graphics_item;
|
||||
ProfTreeWidgetItem* tree_item;
|
||||
unsigned short graphics_item_level;
|
||||
unsigned int graphics_item_index;
|
||||
unsigned int tree_item;
|
||||
unsigned int graphics_item_index;
|
||||
unsigned char graphics_item_level;
|
||||
unsigned char graphics_item;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef ::std::vector<ProfBlock> ProfBlocks;
|
||||
|
||||
|
@ -154,9 +154,11 @@ void ProfMainWindow::loadFile(const std::string& stdfilename)
|
||||
|
||||
m_lastFile = stdfilename;
|
||||
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
|
||||
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
|
||||
::profiler_gui::EASY_GLOBALS.profiler_blocks.swap(prof_blocks);
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks.resize(nblocks);
|
||||
memset(::profiler_gui::EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::ProfBlock) * nblocks);
|
||||
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
|
||||
|
||||
static_cast<ProfGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
|
||||
}
|
||||
@ -179,10 +181,11 @@ void ProfMainWindow::onReloadFileClicked(bool)
|
||||
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
|
||||
|
||||
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
|
||||
::profiler_gui::EASY_GLOBALS.selected_block = -1;
|
||||
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
|
||||
::profiler_gui::EASY_GLOBALS.profiler_blocks.swap(prof_blocks);
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks.resize(nblocks);
|
||||
memset(::profiler_gui::EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::ProfBlock) * nblocks);
|
||||
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
|
||||
|
||||
static_cast<ProfGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
|
||||
}
|
||||
@ -207,10 +210,10 @@ void ProfMainWindow::onTestViewportClicked(bool)
|
||||
::profiler_gui::EASY_GLOBALS.gui_blocks.clear();
|
||||
::profiler_gui::EASY_GLOBALS.profiler_blocks.clear();
|
||||
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
|
||||
::profiler_gui::EASY_GLOBALS.selected_block = -1;
|
||||
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
|
||||
|
||||
view->test(18000, 40000000, 2);
|
||||
//view->test(3, 300, 1);
|
||||
//view->test(18000, 40000000, 2);
|
||||
view->test(100, 9000, 1);
|
||||
}
|
||||
|
||||
void ProfMainWindow::onEncodingChanged(bool)
|
||||
|
Loading…
x
Reference in New Issue
Block a user