0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-26 16:11:02 +08:00

(GUI) Added new regime "Hide min-size blocks" to hide blocks which screen size is less than 'Min blocks size';

(GUI) Slightly more memory effective arch.
This commit is contained in:
Victor Zarubkin 2016-12-12 21:39:16 +03:00
parent 58b1fdb8a3
commit d4877b59b8
11 changed files with 126 additions and 62 deletions

View File

@ -460,7 +460,7 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
if (!t.children.empty())
{
children_duration = setTree(item, ~0U, t.children, h, y, 0);
children_duration = setTree(item, t.children, h, y, 0);
}
else
{
@ -532,7 +532,7 @@ const EasyGraphicsView::Items &EasyGraphicsView::getItems() const
return m_items;
}
qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index_t _parent, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
{
if (_children.empty())
{
@ -540,7 +540,8 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index
}
const auto level = static_cast<uint8_t>(_level);
_item->reserve(level, static_cast<unsigned int>(_children.size()));
const auto n = static_cast<unsigned int>(_children.size());
_item->reserve(level, n);
const short next_level = _level + 1;
bool warned = false;
@ -592,7 +593,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index
if (next_level < 256)
{
children_duration = setTree(_item, child_index, child.children, h, _y + ::profiler_gui::GRAPHICS_ROW_SIZE_FULL, next_level);
children_duration = setTree(_item, child.children, h, _y + ::profiler_gui::GRAPHICS_ROW_SIZE_FULL, next_level);
}
else if (!child.children.empty() && !warned)
{
@ -611,7 +612,7 @@ qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, ::profiler::block_index
}
b.block = child_index;// &child;
b.parent = _parent;
b.neighbours = n;
b.setPos(xbegin, duration);
//b.totalHeight = ::profiler_gui::GRAPHICS_ROW_SIZE + h;
b.state = j > 0 || level == 0 ? 0 : -1;

View File

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

View File

@ -116,16 +116,16 @@ EasyTreeWidget::EasyTreeWidget(QWidget* _parent)
header_item->setText(COL_DURATION, "Duration");
header_item->setText(COL_SELF_DURATION, "Self Dur.");
//header_item->setToolTip(COL_SELF_DURATION, "");
header_item->setText(COL_DURATION_SUM_PER_PARENT, "Tot. Dur./Parent");
header_item->setText(COL_DURATION_SUM_PER_FRAME, "Tot. Dur./Frame");
header_item->setText(COL_DURATION_SUM_PER_THREAD, "Tot. Dur./Thread");
header_item->setText(COL_DURATION_SUM_PER_PARENT, "Sum Dur./Parent");
header_item->setText(COL_DURATION_SUM_PER_FRAME, "Sum Dur./Frame");
header_item->setText(COL_DURATION_SUM_PER_THREAD, "Sum Dur./Thread");
header_item->setText(COL_SELF_DURATION_PERCENT, "Self %");
header_item->setText(COL_PERCENT_PER_PARENT, "% / Parent");
header_item->setText(COL_PERCENT_PER_FRAME, "% / Frame");
header_item->setText(COL_PERCENT_SUM_PER_FRAME, "Tot. % / Frame");
header_item->setText(COL_PERCENT_SUM_PER_PARENT, "Tot. % / Parent");
header_item->setText(COL_PERCENT_SUM_PER_THREAD, "Tot. % / Thread");
header_item->setText(COL_PERCENT_SUM_PER_FRAME, "Sum % / Frame");
header_item->setText(COL_PERCENT_SUM_PER_PARENT, "Sum % / Parent");
header_item->setText(COL_PERCENT_SUM_PER_THREAD, "Sum % / Thread");
header_item->setText(COL_END, "End, ms");
@ -335,16 +335,27 @@ void EasyTreeWidget::clearSilent(bool _global)
if (!_global)
{
if (EASY_GLOBALS.collapse_items_on_tree_close) for (auto item : m_items)
if (EASY_GLOBALS.collapse_items_on_tree_close)
#ifdef EASY_TREE_WIDGET__USE_VECTOR
for (auto item : m_items)
#else
for (auto& item : m_items)
#endif
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
auto& gui_block = item->guiBlock();
::profiler_gui::set_max(gui_block.tree_item);
gui_block.expanded = false;
::profiler_gui::set_max(gui_block.tree_item);
#else
item.second->guiBlock().expanded = false;
#endif
}
#ifdef EASY_TREE_WIDGET__USE_VECTOR
else for (auto item : m_items)
{
::profiler_gui::set_max(item->guiBlock().tree_item);
}
#endif
}
m_items.clear();
@ -656,8 +667,13 @@ void EasyTreeWidget::onCollapseAllClicked(bool)
if (EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
for (auto item : m_items)
item->guiBlock().expanded = false;
#else
for (auto& item : m_items)
item.second->guiBlock().expanded = false;
#endif
emit EASY_GLOBALS.events.itemsExpandStateChanged();
}
}
@ -673,9 +689,13 @@ void EasyTreeWidget::onExpandAllClicked(bool)
if (EASY_GLOBALS.bind_scene_and_tree_expand_status)
{
for (auto item : m_items)
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
for (auto item : m_items){
auto& b = item->guiBlock();
#else
for (auto& item : m_items){
auto& b = item.second->guiBlock();
#endif
b.expanded = !b.tree.children.empty();
}
@ -811,11 +831,19 @@ void EasyTreeWidget::onColorizeRowsTriggered(bool _colorize)
collapseAll(); // Without collapseAll() changing items process is VERY VERY SLOW.
// TODO: Find the reason of such behavior. QSignalBlocker(this) does not help. QSignalBlocker(item) does not work, because items are not inherited from QObject.
#ifdef EASY_TREE_WIDGET__USE_VECTOR
for (auto item : m_items)
{
if (item->parent() != nullptr)
item->colorize(m_bColorRows);
}
#else
for (auto& item : m_items)
{
if (item.second->parent() != nullptr)
item.second->colorize(m_bColorRows);
}
#endif
// Scroll back to previously selected item
if (current)
@ -843,9 +871,15 @@ void EasyTreeWidget::onSelectedBlockChange(uint32_t _block_index)
if (_block_index < EASY_GLOBALS.gui_blocks.size())
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
const auto i = easyBlock(_block_index).tree_item;
if (i < m_items.size())
item = m_items[i];
#else
auto it = m_items.find(_block_index);
if (it != m_items.end())
item = it->second;
#endif
}
if (item != nullptr)

View File

@ -155,13 +155,12 @@ inline ::profiler::color_t textColorForRgb(::profiler::color_t _color)
#pragma pack(push, 1)
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
int8_t state; ///< 0 = no change, 1 = paint, -1 = do not paint
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 neighbours; ///< Number of neighbours (parent.children.size())
uint32_t children_begin; ///< Index of first child item on the next sublevel
int8_t state; ///< 0 = no change, 1 = paint, -1 = do not paint
// 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;
@ -175,10 +174,13 @@ struct EasyBlockItem Q_DECL_FINAL
}; // END of struct EasyBlockItem.
//#define EASY_TREE_WIDGET__USE_VECTOR
struct EasyBlock Q_DECL_FINAL
{
::profiler::BlocksTree tree;
#ifdef EASY_TREE_WIDGET__USE_VECTOR
uint32_t tree_item;
#endif
uint32_t graphics_item_index;
uint8_t graphics_item_level;
uint8_t graphics_item;
@ -188,7 +190,9 @@ struct EasyBlock Q_DECL_FINAL
EasyBlock(EasyBlock&& that)
: tree(::std::move(that.tree))
#ifdef EASY_TREE_WIDGET__USE_VECTOR
, tree_item(that.tree_item)
#endif
, graphics_item_index(that.graphics_item_index)
, graphics_item_level(that.graphics_item_level)
, graphics_item(that.graphics_item)

View File

@ -207,6 +207,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (gotItems)
{
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max<decltype(::profiler_gui::EasyBlockItem::children_begin)>();
const int narrow_size_half = EASY_GLOBALS.blocks_narrow_size >> 1;
//auto const skip_children = [this, &levelsNumber](short next_level, decltype(::profiler_gui::EasyBlockItem::children_begin) children_begin)
//{
// // Mark that we would not paint children of current item
@ -270,30 +272,15 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
{
// This item is not visible
//skip_children(next_level, item.children_begin);
if (item.parent != ~0U)
{
const auto n = static_cast<uint32_t>(easyBlock(item.parent).tree.children.size());
if (neighbour < n)
i += n - neighbour - 1; // Skip all neighbours
}
if (neighbour < item.neighbours)
i += item.neighbours - neighbour - 1; // Skip all neighbours
continue;
}
if (state == BLOCK_ITEM_DO_PAINT_FIRST)
if (state == BLOCK_ITEM_DO_PAINT_FIRST && item.children_begin == MAX_CHILD_INDEX && next_level < levelsNumber && neighbour < (item.neighbours-1))
{
// Paint only first child which has own children
if (item.children_begin == MAX_CHILD_INDEX && next_level < levelsNumber)
continue; // This item has no children and would not be painted
if (item.parent != ~0U)
{
const auto n = static_cast<uint32_t>(easyBlock(item.parent).tree.children.size());
if (neighbour < n)
i += n - neighbour - 1; // Skip all neighbours
}
continue; // This item has no children and would not be painted
}
const auto& itemBlock = easyBlock(item.block);
@ -324,6 +311,18 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
x = prevRight;
}
if (EASY_GLOBALS.hide_minsize_blocks && w < EASY_GLOBALS.blocks_size_min && l > 0)
{
// Hide blocks (except top-level blocks) which width is less than 1 pixel
continue;
}
if (state == BLOCK_ITEM_DO_PAINT_FIRST && neighbour < item.neighbours)
{
// Paint only first child which has own children
i += item.neighbours - neighbour - 1; // Skip all neighbours
}
const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id());
int h = 0, flags = 0;
@ -450,7 +449,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
prevRight = rect.right() + EASY_GLOBALS.blocks_spacing;
if (w < EASY_GLOBALS.blocks_narrow_size)
{
dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT_FIRST);
dont_skip_children(next_level, item.children_begin, w < narrow_size_half ? BLOCK_ITEM_DO_PAINT_FIRST : BLOCK_ITEM_DO_PAINT);
continue;
}

View File

@ -75,6 +75,7 @@ namespace profiler_gui {
, add_zero_blocks_to_hierarchy(false)
, draw_graphics_items_borders(true)
, hide_narrow_children(false)
, hide_minsize_blocks(false)
, display_only_relevant_stats(true)
, collapse_items_on_tree_close(false)
, all_items_expanded_by_default(true)

View File

@ -124,7 +124,8 @@ 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 hide_narrow_children; ///< Hide children for narrow graphics blocks
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)
bool collapse_items_on_tree_close; ///< Collapse all items which were displayed in the hierarchy tree after tree close/reset
bool all_items_expanded_by_default; ///< Expand all items after file is opened

View File

@ -264,13 +264,19 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_lastAddress("localhost"), m_lastP
action->setToolTip("Draw borders for blocks on diagram.\nThis reduces performance.");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
connect(action, &QAction::triggered, this, &This::onDrawBordersChanged);
connect(action, &QAction::triggered, [this](bool _checked){ EASY_GLOBALS.draw_graphics_items_borders = _checked; refreshDiagram(); });
action = submenu->addAction("Hide narrow children");
action->setToolTip("Children blocks will be hidden by narrow\nparent blocks. See also \"Blocks narrow size\".\nThis improves performance.");
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.");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.hide_narrow_children);
connect(action, &QAction::triggered, this, &This::onHideNarrowChildrenChanged);
connect(action, &QAction::triggered, [this](bool _checked){ EASY_GLOBALS.hide_narrow_children = _checked; refreshDiagram(); });
action = submenu->addAction("Hide min-size blocks");
action->setToolTip("Hides blocks which screen size\nis less than \'Min blocks size\'.");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.hide_minsize_blocks);
connect(action, &QAction::triggered, [this](bool _checked){ EASY_GLOBALS.hide_minsize_blocks = _checked; refreshDiagram(); });
action = submenu->addAction("Build hierarchy only for current thread");
action->setToolTip("Hierarchy tree will be built\nfor blocks from current thread only.\nThis improves performance\nand saves a lot of memory.");
@ -798,18 +804,6 @@ void EasyMainWindow::onEnableDisableStatistics(bool _checked)
}
}
void EasyMainWindow::onDrawBordersChanged(bool _checked)
{
EASY_GLOBALS.draw_graphics_items_borders = _checked;
refreshDiagram();
}
void EasyMainWindow::onHideNarrowChildrenChanged(bool _checked)
{
EASY_GLOBALS.hide_narrow_children = _checked;
refreshDiagram();
}
void EasyMainWindow::onCollapseItemsAfterCloseChanged(bool _checked)
{
EASY_GLOBALS.collapse_items_on_tree_close = _checked;
@ -979,6 +973,10 @@ void EasyMainWindow::loadSettings()
if (!flag.isNull())
EASY_GLOBALS.hide_narrow_children = flag.toBool();
flag = settings.value("hide_minsize_blocks");
if (!flag.isNull())
EASY_GLOBALS.hide_minsize_blocks = flag.toBool();
flag = settings.value("collapse_items_on_tree_close");
if (!flag.isNull())
EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool();
@ -1062,6 +1060,7 @@ void EasyMainWindow::saveSettingsAndGeometry()
settings.setValue("blocks_narrow_size", EASY_GLOBALS.blocks_narrow_size);
settings.setValue("draw_graphics_items_borders", EASY_GLOBALS.draw_graphics_items_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);
settings.setValue("all_items_expanded_by_default", EASY_GLOBALS.all_items_expanded_by_default);
settings.setValue("only_current_thread_hierarchy", EASY_GLOBALS.only_current_thread_hierarchy);
@ -1208,7 +1207,9 @@ void EasyMainWindow::onFileReaderTimeout()
for (decltype(nblocks) i = 0; i < nblocks; ++i) {
auto& guiblock = EASY_GLOBALS.gui_blocks[i];
guiblock.tree = ::std::move(blocks[i]);
#ifdef EASY_TREE_WIDGET__USE_VECTOR
::profiler_gui::set_max(guiblock.tree_item);
#endif
}
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(EASY_GLOBALS.profiler_blocks);

View File

@ -238,8 +238,6 @@ protected slots:
void onUnitsChanged(bool);
void onEventIndicatorsChange(bool);
void onEnableDisableStatistics(bool);
void onDrawBordersChanged(bool);
void onHideNarrowChildrenChanged(bool);
void onCollapseItemsAfterCloseChanged(bool);
void onAllItemsExpandedByDefaultChange(bool);
void onBindExpandStatusChange(bool);

View File

@ -399,8 +399,10 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
item->setBackgroundColor(color);
item->setTextColor(fgColor);
#ifdef EASY_TREE_WIDGET__USE_VECTOR
auto item_index = static_cast<unsigned int>(_items.size());
_items.push_back(item);
#endif
size_t children_items_number = 0;
::profiler::timestamp_t children_duration = 0;
@ -425,7 +427,9 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
//total_items += children_items_number + 1;
#ifdef EASY_TREE_WIDGET__USE_VECTOR
gui_block.tree_item = item_index;
#endif
if (_colorizeRows)
item->colorize(_colorizeRows);
@ -433,10 +437,15 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
if (gui_block.expanded)
item->setExpanded(true);
#ifndef EASY_TREE_WIDGET__USE_VECTOR
_items.insert(::std::make_pair(block.tree, item));
#endif
}
else
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
_items.pop_back();
#endif
delete item;
}
@ -612,8 +621,10 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
item->setBackgroundColor(color);
item->setTextColor(fgColor);
#ifdef EASY_TREE_WIDGET__USE_VECTOR
auto item_index = static_cast<uint32_t>(_items.size());
_items.push_back(item);
#endif
size_t children_items_number = 0;
::profiler::timestamp_t children_duration = 0;
@ -638,17 +649,25 @@ size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
total_items += children_items_number + 1;
#ifdef EASY_TREE_WIDGET__USE_VECTOR
gui_block.tree_item = item_index;
#endif
if (_colorizeRows)
item->colorize(_colorizeRows);
if (gui_block.expanded)
item->setExpanded(true);
#ifndef EASY_TREE_WIDGET__USE_VECTOR
_items.insert(::std::make_pair(child_index, item));
#endif
}
else
{
#ifdef EASY_TREE_WIDGET__USE_VECTOR
_items.pop_back();
#endif
delete item;
}
}

View File

@ -57,7 +57,13 @@
//////////////////////////////////////////////////////////////////////////
class EasyTreeWidgetItem;
#ifndef EASY_TREE_WIDGET__USE_VECTOR
typedef ::std::unordered_map<::profiler::block_index_t, EasyTreeWidgetItem*, ::profiler_gui::do_no_hash<::profiler::block_index_t>::hasher_t> Items;
#else
typedef ::std::vector<EasyTreeWidgetItem*> Items;
#endif
typedef ::std::vector<::std::pair<::profiler::thread_id_t, EasyTreeWidgetItem*> > ThreadedItems;
typedef ::std::unordered_map<::profiler::thread_id_t, EasyTreeWidgetItem*, ::profiler_gui::do_no_hash<::profiler::thread_id_t>::hasher_t> RootsMap;