0
0
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:
Victor Zarubkin 2016-08-11 23:43:34 +03:00
parent 6df717781a
commit 24f181c040
6 changed files with 175 additions and 123 deletions

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
}
//////////////////////////////////////////////////////////////////////////

View File

@ -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.
//////////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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)