0
0
mirror of https://github.com/yse/easy_profiler.git synced 2025-01-14 00:27:55 +08:00

GUI: Blocks painting algorithm optimization for detailed mode

This commit is contained in:
Victor Zarubkin 2016-11-19 03:46:52 +03:00
parent cdea3b805f
commit ed3e26a59c
4 changed files with 77 additions and 23 deletions

View File

@ -454,7 +454,7 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
if (!t.children.empty())
{
children_duration = setTree(item, t.children, h, y, 0);
children_duration = setTree(item, ~0U, t.children, h, y, 0);
}
else
{
@ -522,7 +522,7 @@ const EasyGraphicsView::Items &EasyGraphicsView::getItems() const
return m_items;
}
qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index_t _parent, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
{
static const qreal MIN_DURATION = 0.25;
@ -538,6 +538,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
bool warned = false;
qreal total_duration = 0, prev_end = 0, maxh = 0;
qreal start_time = -1;
uint32_t i = 0;
for (auto child_index : _children)
{
auto& gui_block = easyBlock(child_index);
@ -584,7 +585,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
if (next_level < 256)
{
children_duration = setTree(_item, child.children, h, _y + ::profiler_gui::GRAPHICS_ROW_SIZE_FULL, next_level);
children_duration = setTree(_item, child_index, child.children, h, _y + ::profiler_gui::GRAPHICS_ROW_SIZE_FULL, next_level);
}
else if (!child.children.empty() && !warned)
{
@ -603,12 +604,15 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::Block
}
b.block = child_index;// &child;
b.parent = _parent;
b.setPos(xbegin, duration);
b.totalHeight = ::profiler_gui::GRAPHICS_ROW_SIZE + h;
b.state = 0;
//b.totalHeight = ::profiler_gui::GRAPHICS_ROW_SIZE + h;
b.state = i > 0 || level == 0 ? 0 : -1;
prev_end = xbegin + duration;
total_duration = prev_end - start_time;
++i;
}
_height += ::profiler_gui::GRAPHICS_ROW_SIZE_FULL + maxh;

View File

@ -182,7 +182,7 @@ private:
void updateTimelineStep(qreal _windowWidth);
void scaleTo(qreal _scale);
void onWheel(qreal _mouseX, int _wheelDelta);
qreal setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level);
qreal setTree(EasyGraphicsItem* _item, ::profiler::block_index_t _parent, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level);
private slots:

View File

@ -153,8 +153,9 @@ struct EasyBlockItem Q_DECL_FINAL
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
::profiler::block_index_t block; ///< Index of profiler block
::profiler::block_index_t parent; ///< Index of parent profiler block
uint32_t children_begin; ///< Index of first child item on the next sublevel
uint16_t totalHeight; ///< Total height of the item including heights of all it's children
//uint16_t totalHeight; ///< Total height of the item including heights of all it's children
int8_t state; ///< 0 = no change, 1 = paint, -1 = do not paint
// Possible optimizations:

View File

@ -54,6 +54,7 @@
enum BlockItemState : int8_t
{
BLOCK_ITEM_DO_PAINT_FIRST = -2,
BLOCK_ITEM_DO_NOT_PAINT = -1,
BLOCK_ITEM_UNCHANGED,
BLOCK_ITEM_DO_PAINT
@ -62,7 +63,7 @@ enum BlockItemState : int8_t
//////////////////////////////////////////////////////////////////////////
const int MIN_ITEM_WIDTH = 3;
const int MIN_ITEMS_SPACING = 3;
const int MIN_ITEMS_SPACING = 2;
const int MIN_SYNC_SPACING = 1;
const int NARROW_ITEM_WIDTH = 20;
const QRgb BORDERS_COLOR = ::profiler::colors::Grey700 & 0x00ffffff;// 0x00686868;
@ -211,7 +212,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
m_levels[next_level][children_begin].state = BLOCK_ITEM_DO_NOT_PAINT;
};
auto const dont_skip_children = [this, &levelsNumber](short next_level, decltype(::profiler_gui::EasyBlockItem::children_begin) children_begin)
auto const dont_skip_children = [this, &levelsNumber](short next_level, decltype(::profiler_gui::EasyBlockItem::children_begin) children_begin, int8_t _state)
{
if (next_level < levelsNumber && children_begin != MAX_CHILD_INDEX)
{
@ -222,10 +223,11 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
// Mark children items that we want to draw them
m_levels[next_level][children_begin].state = BLOCK_ITEM_DO_PAINT;
m_levels[next_level][children_begin].state = _state;
}
};
//size_t iterations = 0;
bool selectedItemsWasPainted = false;
for (uint8_t l = 0; l < levelsNumber; ++l)
{
@ -237,9 +239,13 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (top > visibleBottom)
break;
int j = 1;
uint32_t par = ~0U;
qreal prevRight = -1e100;
for (unsigned int i = m_levelsIndexes[l], end = static_cast<unsigned int>(level.size()); i < end; ++i)
for (uint32_t i = m_levelsIndexes[l], end = static_cast<uint32_t>(level.size()); i < end; ++i)
{
//++iterations;
auto& item = level[i];
if (item.left() > sceneRight)
@ -248,12 +254,51 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (item.state != BLOCK_ITEM_UNCHANGED)
{
state = item.state;
item.state = BLOCK_ITEM_DO_NOT_PAINT;
}
if (item.right() < sceneLeft || state == BLOCK_ITEM_DO_NOT_PAINT || (top + item.totalHeight) < visibleSceneRect.top())
if (item.right() < sceneLeft)
{
// This item is not visible
skip_children(next_level, item.children_begin);
//skip_children(next_level, item.children_begin);
continue;
}
if (state == BLOCK_ITEM_DO_NOT_PAINT)
{
// This item is not visible
//skip_children(next_level, item.children_begin);
if (item.parent != ~0U)
i += static_cast<uint32_t>(easyBlock(item.parent).tree.children.size()) - 1; // Skip all neighbours
continue;
}
if (state == BLOCK_ITEM_DO_PAINT_FIRST)
{
// Paint only first child which has own children
if (par != item.parent)
j = 1;
par = item.parent;
if (item.children_begin == MAX_CHILD_INDEX && next_level < levelsNumber)
{
// This item has no children and would not be painted
++j;
continue;
}
if (item.parent != ~0U)
i += static_cast<uint32_t>(easyBlock(item.parent).tree.children.size()) - j; // Skip all neighbours
}
const auto& itemBlock = easyBlock(item.block);
const uint16_t totalHeight = itemBlock.tree.depth * ::profiler_gui::GRAPHICS_ROW_SIZE_FULL + ::profiler_gui::GRAPHICS_ROW_SIZE;
if ((top + totalHeight) < visibleSceneRect.top())
{
// This item is not visible
//skip_children(next_level, item.children_begin);
continue;
}
@ -262,10 +307,10 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (x + w <= prevRight)
{
// This item is not visible
if (EASY_GLOBALS.hide_narrow_children && w < NARROW_ITEM_WIDTH)
skip_children(next_level, item.children_begin);
else
dont_skip_children(next_level, item.children_begin);
if (!(EASY_GLOBALS.hide_narrow_children && w < NARROW_ITEM_WIDTH) && l > 0)
dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT_FIRST);
//else
// skip_children(next_level, item.children_begin);
continue;
}
@ -275,7 +320,6 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
x = prevRight;
}
const auto& itemBlock = easyBlock(item.block);
const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id());
int h = 0, flags = 0;
@ -284,7 +328,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
// Items which width is less than 20 will be painted as big rectangles which are hiding it's children
//x = item.left() * currentScale - dx;
h = item.totalHeight;
h = totalHeight;
const auto dh = top + h - visibleBottom;
if (dh > 0)
h -= dh;
@ -318,11 +362,11 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->drawRect(rect);
prevRight = rect.right() + MIN_ITEMS_SPACING;
skip_children(next_level, item.children_begin);
//skip_children(next_level, item.children_begin);
if (w < NARROW_ITEM_WIDTH)
continue;
if (item.totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE)
if (totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE)
flags = Qt::AlignCenter;
else if (!(item.width() < 1))
flags = Qt::AlignHCenter;
@ -364,10 +408,13 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->drawRect(rect);
prevRight = rect.right() + MIN_ITEMS_SPACING;
dont_skip_children(next_level, item.children_begin);
if (w < NARROW_ITEM_WIDTH)
{
dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT_FIRST);
continue;
}
dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT);
if (!(item.width() < 1))
flags = Qt::AlignHCenter;
}
@ -426,7 +473,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
const auto& itemBlock = easyBlock(item.block);
auto top = levelY(guiblock.graphics_item_level);
auto w = ::std::max(item.width() * currentScale, 1.0);
decltype(top) h = (!itemBlock.expanded || (w < NARROW_ITEM_WIDTH && EASY_GLOBALS.hide_narrow_children)) ? item.totalHeight : ::profiler_gui::GRAPHICS_ROW_SIZE;
decltype(top) h = (!itemBlock.expanded || (w < NARROW_ITEM_WIDTH && EASY_GLOBALS.hide_narrow_children)) ? (itemBlock.tree.depth * ::profiler_gui::GRAPHICS_ROW_SIZE_FULL + ::profiler_gui::GRAPHICS_ROW_SIZE) : ::profiler_gui::GRAPHICS_ROW_SIZE;
auto dh = top + h - visibleBottom;
if (dh < h)
@ -493,6 +540,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
}
}
//printf("%u: %llu\n", m_index, iterations);
}