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

Merge remote-tracking branch 'origin/develop' into rename_to_easy

This commit is contained in:
Sergey Yagovtsev 2016-10-21 22:15:32 +03:00
commit f8ab7f0d91
25 changed files with 863 additions and 301 deletions

View File

@ -23,7 +23,7 @@ You can see the results of measuring in simple GUI application which provides fu
# Usage # Usage
First of all you can specify path to include directory which contains `include/profiler` directory. First of all you can specify path to include directory which contains `include/profiler` directory and define macro `BUILD_WITH_EASY_PROFILER`.
For linking with easy_profiler you can specify path to library. For linking with easy_profiler you can specify path to library.
Example of usage. Example of usage.

View File

@ -33,7 +33,7 @@ namespace profiler {
const uint32_t EASY_FULL_VERSION = ((uint32_t)EASY_VERSION_MAJOR << 24) | ((uint32_t)EASY_VERSION_MINOR << 16) | (uint32_t)EASY_VERSION_REV; const uint32_t EASY_FULL_VERSION = ((uint32_t)EASY_VERSION_MAJOR << 24) | ((uint32_t)EASY_VERSION_MINOR << 16) | (uint32_t)EASY_VERSION_REV;
} }
#ifndef FULL_DISABLE_PROFILER #ifdef BUILD_WITH_EASY_PROFILER
/** /**
\defgroup profiler EasyProfiler \defgroup profiler EasyProfiler
@ -212,7 +212,6 @@ breakdown, but if you care about that then you change set event tracing priority
*/ */
# define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority) ::profiler::setLowPriorityEventTracing(isLowPriority); # define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority) ::profiler::setLowPriorityEventTracing(isLowPriority);
# ifndef _WIN32
/** Macro for setting temporary log-file path for Unix event tracing system. /** Macro for setting temporary log-file path for Unix event tracing system.
\note Default value is "/tmp/cs_profiling_info.log". \note Default value is "/tmp/cs_profiling_info.log".
@ -226,9 +225,6 @@ breakdown, but if you care about that then you change set event tracing priority
\ingroup profiler \ingroup profiler
*/ */
# define EASY_EVENT_TRACING_LOG ::profiler::getContextSwitchLogFilename(); # define EASY_EVENT_TRACING_LOG ::profiler::getContextSwitchLogFilename();
# endif
// EasyProfiler settings: // EasyProfiler settings:
@ -279,7 +275,7 @@ Otherwise, no log messages will be printed.
# define EASY_LOG_ENABLED 1 # define EASY_LOG_ENABLED 1
#else // #ifndef FULL_DISABLE_PROFILER #else // #ifdef BUILD_WITH_EASY_PROFILER
# define EASY_BLOCK(...) # define EASY_BLOCK(...)
# define EASY_FUNCTION(...) # define EASY_FUNCTION(...)
@ -303,7 +299,7 @@ Otherwise, no log messages will be printed.
# define EASY_LOW_PRIORITY_EVENT_TRACING true # define EASY_LOW_PRIORITY_EVENT_TRACING true
# define EASY_LOG_ENABLED 0 # define EASY_LOG_ENABLED 0
#endif // #ifndef FULL_DISABLE_PROFILER #endif // #ifndef BUILD_WITH_EASY_PROFILER
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -515,7 +511,6 @@ namespace profiler {
*/ */
PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority); PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority);
#ifndef _WIN32
/** Set temporary log-file path for Unix event tracing system. /** Set temporary log-file path for Unix event tracing system.
\note Default value is "/tmp/cs_profiling_info.log". \note Default value is "/tmp/cs_profiling_info.log".
@ -529,7 +524,6 @@ namespace profiler {
\ingroup profiler \ingroup profiler
*/ */
PROFILER_API const char* getContextSwitchLogFilename(); PROFILER_API const char* getContextSwitchLogFilename();
#endif
PROFILER_API void startListenSignalToCapture(); PROFILER_API void startListenSignalToCapture();
PROFILER_API void stopListenSignalToCapture(); PROFILER_API void stopListenSignalToCapture();

View File

@ -48,18 +48,16 @@ namespace profiler {
FORCE_ON_WITHOUT_CHILDREN = FORCE_ON | OFF_RECURSIVE, ///< The block is ALWAYS ON but all of it's children are OFF. FORCE_ON_WITHOUT_CHILDREN = FORCE_ON | OFF_RECURSIVE, ///< The block is ALWAYS ON but all of it's children are OFF.
}; };
struct passthrough_hash EASY_FINAL { struct passthrough_hash EASY_FINAL {
template <class T> inline size_t operator () (T _value) const { template <class T> inline size_t operator () (T _value) const {
return static_cast<size_t>(_value); return static_cast<size_t>(_value);
} }
}; };
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef FULL_DISABLE_PROFILER
#include <type_traits> #include <type_traits>
#include <string> #include <string>
@ -70,6 +68,8 @@ namespace profiler {
# define EASY_UNIQUE_BLOCK(x) EASY_TOKEN_CONCATENATE(unique_profiler_mark_name_, x) # define EASY_UNIQUE_BLOCK(x) EASY_TOKEN_CONCATENATE(unique_profiler_mark_name_, x)
# define EASY_UNIQUE_DESC(x) EASY_TOKEN_CONCATENATE(unique_profiler_descriptor_, x) # define EASY_UNIQUE_DESC(x) EASY_TOKEN_CONCATENATE(unique_profiler_descriptor_, x)
#ifdef BUILD_WITH_EASY_PROFILER
namespace profiler { namespace profiler {
template <const bool IS_REF> struct NameSwitch EASY_FINAL { template <const bool IS_REF> struct NameSwitch EASY_FINAL {
@ -147,7 +147,7 @@ namespace profiler {
# define EASY_COMPILETIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::compiletime_name(name, EASY_UNIQUE_LINE_ID) # define EASY_COMPILETIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::compiletime_name(name, EASY_UNIQUE_LINE_ID)
# define EASY_RUNTIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::runtime_name(name) # define EASY_RUNTIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::runtime_name(name)
#endif // FULL_DISABLE_PROFILER #endif // BUILD_WITH_EASY_PROFILER
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -260,8 +260,8 @@ namespace profiler {
clear(); clear();
} }
void set(size_t _size); void set(uint64_t _size);
void extend(size_t _size); void extend(uint64_t _size);
SerializedData& operator = (SerializedData&& that) SerializedData& operator = (SerializedData&& that)
{ {
@ -276,7 +276,17 @@ namespace profiler {
return m_data + i; return m_data + i;
} }
size_t size() const const char* operator [] (uint64_t i) const
{
return m_data + i;
}
bool empty() const
{
return m_size == 0;
}
uint64_t size() const
{ {
return m_size; return m_size;
} }
@ -299,7 +309,7 @@ namespace profiler {
void swap(SerializedData& other) void swap(SerializedData& other)
{ {
char* d = other.m_data; char* d = other.m_data;
size_t sz = other.m_size; uint64_t sz = other.m_size;
other.m_data = m_data; other.m_data = m_data;
other.m_size = m_size; other.m_size = m_size;
@ -310,7 +320,7 @@ namespace profiler {
private: private:
void set(char* _data, size_t _size); void set(char* _data, uint64_t _size);
SerializedData(const SerializedData&) = delete; SerializedData(const SerializedData&) = delete;
SerializedData& operator = (const SerializedData&) = delete; SerializedData& operator = (const SerializedData&) = delete;
@ -319,6 +329,51 @@ namespace profiler {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct FileData
{
::profiler::SerializedData serialized_blocks;
::profiler::SerializedData serialized_descriptors;
::std::vector<::profiler::thread_id_t> threads_order;
::profiler::timestamp_t begin_time = 0ULL;
::profiler::timestamp_t end_time = 0ULL;
int64_t cpu_frequency = 0LL;
uint32_t total_blocks_number = 0;
uint32_t total_descriptors_number = 0;
FileData() = default;
FileData(FileData&& _other)
: serialized_blocks(::std::move(_other.serialized_blocks))
, serialized_descriptors(::std::move(_other.serialized_descriptors))
, threads_order(::std::move(_other.threads_order))
, begin_time(_other.begin_time)
, end_time(_other.end_time)
, cpu_frequency(_other.cpu_frequency)
, total_blocks_number(_other.total_blocks_number)
, total_descriptors_number(_other.total_descriptors_number)
{
}
FileData& operator = (FileData&& _other)
{
serialized_blocks = ::std::move(_other.serialized_blocks);
serialized_descriptors = ::std::move(_other.serialized_descriptors);
threads_order = ::std::move(_other.threads_order);
begin_time = _other.begin_time;
end_time = _other.end_time;
cpu_frequency = _other.cpu_frequency;
total_blocks_number = _other.total_blocks_number;
total_descriptors_number = _other.total_descriptors_number;
return *this;
}
private:
FileData(const FileData&) = delete;
FileData& operator = (const FileData&) = delete;
};
//////////////////////////////////////////////////////////////////////////
typedef ::std::vector<SerializedBlockDescriptor*> descriptors_list_t; typedef ::std::vector<SerializedBlockDescriptor*> descriptors_list_t;
} // END of namespace profiler. } // END of namespace profiler.
@ -326,22 +381,24 @@ namespace profiler {
extern "C" { extern "C" {
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename, PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics, uint32_t& total_descriptors_number,
::std::stringstream& _log); bool gather_statistics,
::std::stringstream& _log);
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str, PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics, uint32_t& total_descriptors_number,
::std::stringstream& _log); bool gather_statistics,
::std::stringstream& _log);
PROFILER_API bool readDescriptionsFromStream(::std::atomic<int>& progress, ::std::stringstream& str, PROFILER_API bool readDescriptionsFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
@ -350,13 +407,15 @@ extern "C" {
} }
inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log) ::std::stringstream& _log)
{ {
::std::atomic<int> progress = ATOMIC_VAR_INIT(0); ::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, gather_statistics, _log); return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, total_descriptors_number, gather_statistics, _log);
} }
inline bool readDescriptionsFromStream(::std::stringstream& str, inline bool readDescriptionsFromStream(::std::stringstream& str,

View File

@ -614,7 +614,7 @@ void EasyTreeWidget::onBlockStatusChangeClicked(bool _checked)
void EasyTreeWidget::onItemExpand(QTreeWidgetItem* _item) void EasyTreeWidget::onItemExpand(QTreeWidgetItem* _item)
{ {
if (!EASY_GLOBALS.bind_scene_and_tree_expand_status) if (!EASY_GLOBALS.bind_scene_and_tree_expand_status || _item->parent() == nullptr)
{ {
resizeColumnsToContents(); resizeColumnsToContents();
return; return;
@ -631,7 +631,7 @@ void EasyTreeWidget::onItemExpand(QTreeWidgetItem* _item)
void EasyTreeWidget::onItemCollapse(QTreeWidgetItem* _item) void EasyTreeWidget::onItemCollapse(QTreeWidgetItem* _item)
{ {
if (!EASY_GLOBALS.bind_scene_and_tree_expand_status) if (!EASY_GLOBALS.bind_scene_and_tree_expand_status || _item->parent() == nullptr)
return; return;
static_cast<EasyTreeWidgetItem*>(_item)->guiBlock().expanded = false; static_cast<EasyTreeWidgetItem*>(_item)->guiBlock().expanded = false;

View File

@ -150,18 +150,17 @@ inline ::profiler::color_t textColorForRgb(::profiler::color_t _color)
#pragma pack(push, 1) #pragma pack(push, 1)
struct EasyBlockItem Q_DECL_FINAL struct EasyBlockItem Q_DECL_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) 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 w; ///< Width of the item
::profiler::block_index_t block; ///< Index of profiler block ::profiler::block_index_t block; ///< Index of profiler block
uint32_t children_begin; ///< Index of first child item on the next sublevel 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
char state; ///< 0 = no change, 1 = paint, -1 = do not paint int8_t state; ///< 0 = no change, 1 = paint, -1 = do not paint
// Possible optimizations: // 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; // 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), // 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. // but this requires runtime x-coodinate calculation because BlocksTree has x value in nanoseconds.
inline void setPos(qreal _x, float _w) { x = _x; w = _w; } inline void setPos(qreal _x, float _w) { x = _x; w = _w; }
inline qreal left() const { return x; } inline qreal left() const { return x; }

View File

@ -696,6 +696,7 @@ EasyDescWidget::EasyDescWidget(QWidget* _parent) : Parent(_parent)
, m_searchButton(nullptr) , m_searchButton(nullptr)
{ {
m_searchBox->setFixedWidth(200); m_searchBox->setFixedWidth(200);
m_searchBox->setContentsMargins(5, 0, 0, 0);
auto tb = new QToolBar(); auto tb = new QToolBar();
auto refreshButton = tb->addAction(QIcon(":/Reload"), tr("Refresh blocks list")); auto refreshButton = tb->addAction(QIcon(":/Reload"), tr("Refresh blocks list"));
@ -703,26 +704,32 @@ EasyDescWidget::EasyDescWidget(QWidget* _parent) : Parent(_parent)
refreshButton->setToolTip(tr("Refresh blocks list.\nConnection needed.")); refreshButton->setToolTip(tr("Refresh blocks list.\nConnection needed."));
connect(refreshButton, &QAction::triggered, &EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::blocksRefreshRequired); connect(refreshButton, &QAction::triggered, &EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::blocksRefreshRequired);
tb->addSeparator();
m_searchButton = tb->addAction(QIcon(":/Search-next"), tr("Find next"), this, SLOT(findNext(bool)));
tb->addWidget(m_searchBox);
m_searchButton->setData(true);
m_searchButton->setMenu(new QMenu(this));
QMenu* menu = new QMenu(this);
m_searchButton = menu->menuAction();
m_searchButton->setText("Find next");
m_searchButton->setIcon(QIcon(":/Search-next"));
m_searchButton->setData(true);
connect(m_searchButton, &QAction::triggered, this, &This::findNext);
auto actionGroup = new QActionGroup(this); auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true); actionGroup->setExclusive(true);
auto a = new QAction(tr("Find next"), actionGroup); auto a = new QAction(tr("Find next"), actionGroup);
a->setCheckable(true); a->setCheckable(true);
a->setChecked(true); a->setChecked(true);
connect(a, &QAction::triggered, this, &This::findNextFromMenu); connect(a, &QAction::triggered, this, &This::findNextFromMenu);
m_searchButton->menu()->addAction(a); menu->addAction(a);
a = new QAction(tr("Find previous"), actionGroup); a = new QAction(tr("Find previous"), actionGroup);
a->setCheckable(true); a->setCheckable(true);
connect(a, &QAction::triggered, this, &This::findPrevFromMenu); connect(a, &QAction::triggered, this, &This::findPrevFromMenu);
m_searchButton->menu()->addAction(a); menu->addAction(a);
tb->addSeparator();
tb->addAction(m_searchButton);
tb->addWidget(m_searchBox);
auto searchbox = new QHBoxLayout(); auto searchbox = new QHBoxLayout();
searchbox->setContentsMargins(0, 0, 0, 0); searchbox->setContentsMargins(0, 0, 0, 0);

View File

@ -38,7 +38,7 @@
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
enum BlockItemState enum BlockItemState : int8_t
{ {
BLOCK_ITEM_DO_NOT_PAINT = -1, BLOCK_ITEM_DO_NOT_PAINT = -1,
BLOCK_ITEM_UNCHANGED, BLOCK_ITEM_UNCHANGED,
@ -47,6 +47,10 @@ enum BlockItemState
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
const int MIN_ITEM_WIDTH = 3;
const int MIN_ITEMS_SPACING = 3;
const int MIN_SYNC_SPACING = 1;
const int NARROW_ITEM_WIDTH = 20;
const QRgb BORDERS_COLOR = ::profiler::colors::Grey700 & 0x00ffffff;// 0x00686868; const QRgb BORDERS_COLOR = ::profiler::colors::Grey700 & 0x00ffffff;// 0x00686868;
inline QRgb selectedItemBorderColor(::profiler::color_t _color) { inline QRgb selectedItemBorderColor(::profiler::color_t _color) {
@ -69,10 +73,22 @@ const auto SELECTED_ITEM_FONT = ::profiler_gui::EFont("Helvetica", 10, QFont::Bo
EasyGraphicsItem::EasyGraphicsItem(uint8_t _index, const::profiler::BlocksTreeRoot& _root) EasyGraphicsItem::EasyGraphicsItem(uint8_t _index, const::profiler::BlocksTreeRoot& _root)
: QGraphicsItem(nullptr) : QGraphicsItem(nullptr)
, m_threadName(_root.got_name() ? QString("%1 Thread %2").arg(_root.name()).arg(_root.thread_id) : QString("Thread %1").arg(_root.thread_id))
, m_pRoot(&_root) , m_pRoot(&_root)
, m_index(_index) , m_index(_index)
{ {
const auto u_thread = ::profiler_gui::toUnicode("thread");
if (_root.got_name())
{
QString rootname(::profiler_gui::toUnicode(_root.name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
m_threadName = ::std::move(QString("%1 %2").arg(rootname).arg(_root.thread_id));
else
m_threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(_root.thread_id));
}
else
{
m_threadName = ::std::move(QString("Thread %1").arg(_root.thread_id));
}
} }
EasyGraphicsItem::~EasyGraphicsItem() EasyGraphicsItem::~EasyGraphicsItem()
@ -181,6 +197,21 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
m_levels[next_level][children_begin].state = BLOCK_ITEM_DO_NOT_PAINT; 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)
{
if (next_level < levelsNumber && children_begin != MAX_CHILD_INDEX)
{
if (m_levelsIndexes[next_level] == MAX_CHILD_INDEX)
{
// Mark first potentially visible child item on next sublevel
m_levelsIndexes[next_level] = children_begin;
}
// Mark children items that we want to draw them
m_levels[next_level][children_begin].state = BLOCK_ITEM_DO_PAINT;
}
};
bool selectedItemsWasPainted = false; bool selectedItemsWasPainted = false;
for (uint8_t l = 0; l < levelsNumber; ++l) for (uint8_t l = 0; l < levelsNumber; ++l)
{ {
@ -209,21 +240,29 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
continue; continue;
} }
const auto x = item.left() * currentScale - dx; auto x = item.left() * currentScale - dx;
auto w = item.width() * currentScale; auto w = item.width() * currentScale;
if (x + w <= prevRight) if (x + w <= prevRight)
{ {
// This item is not visible // This item is not visible
if (w < 20) if (EASY_GLOBALS.hide_narrow_children && w < NARROW_ITEM_WIDTH)
skip_children(next_level, item.children_begin); skip_children(next_level, item.children_begin);
else
dont_skip_children(next_level, item.children_begin);
continue; continue;
} }
if (x < prevRight)
{
w -= prevRight - x;
x = prevRight;
}
const auto& itemBlock = easyBlock(item.block); const auto& itemBlock = easyBlock(item.block);
const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id()); const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id());
int h = 0, flags = 0; int h = 0, flags = 0;
if (w < 20 || !itemBlock.expanded) if ((EASY_GLOBALS.hide_narrow_children && w < NARROW_ITEM_WIDTH) || !itemBlock.expanded)
{ {
// Items which width is less than 20 will be painted as big rectangles which are hiding it's children // Items which width is less than 20 will be painted as big rectangles which are hiding it's children
@ -254,15 +293,16 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setPen(BORDERS_COLOR & inverseColor);// BORDERS_COLOR); _painter->setPen(BORDERS_COLOR & inverseColor);// BORDERS_COLOR);
} }
if (w < 2) w = 2; if (w < MIN_ITEM_WIDTH)
w = MIN_ITEM_WIDTH;
// Draw rectangle // Draw rectangle
rect.setRect(x, top, w, h); rect.setRect(x, top, w, h);
_painter->drawRect(rect); _painter->drawRect(rect);
prevRight = rect.right(); prevRight = rect.right() + MIN_ITEMS_SPACING;
skip_children(next_level, item.children_begin); skip_children(next_level, item.children_begin);
if (w < 20) if (w < NARROW_ITEM_WIDTH)
continue; continue;
if (item.totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE) if (item.totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE)
@ -272,18 +312,6 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
} }
else else
{ {
if (next_level < levelsNumber && item.children_begin != MAX_CHILD_INDEX)
{
if (m_levelsIndexes[next_level] == MAX_CHILD_INDEX)
{
// Mark first potentially visible child item on next sublevel
m_levelsIndexes[next_level] = item.children_begin;
}
// Mark children items that we want to draw them
m_levels[next_level][item.children_begin].state = BLOCK_ITEM_DO_PAINT;
}
if (item.block == EASY_GLOBALS.selected_block) if (item.block == EASY_GLOBALS.selected_block)
selectedItemsWasPainted = true; selectedItemsWasPainted = true;
@ -312,13 +340,19 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (dh > 0) if (dh > 0)
h -= dh; h -= dh;
if (w < MIN_ITEM_WIDTH)
w = MIN_ITEM_WIDTH;
rect.setRect(x, top, w, h); rect.setRect(x, top, w, h);
_painter->drawRect(rect); _painter->drawRect(rect);
prevRight = rect.right() + MIN_ITEMS_SPACING;
dont_skip_children(next_level, item.children_begin);
if (w < NARROW_ITEM_WIDTH)
continue;
if (!(item.width() < 1)) if (!(item.width() < 1))
flags = Qt::AlignHCenter; flags = Qt::AlignHCenter;
prevRight = rect.right();
} }
// Draw text----------------------------------- // Draw text-----------------------------------
@ -375,7 +409,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
const auto& itemBlock = easyBlock(item.block); const auto& itemBlock = easyBlock(item.block);
auto top = levelY(guiblock.graphics_item_level); auto top = levelY(guiblock.graphics_item_level);
auto w = ::std::max(item.width() * currentScale, 1.0); auto w = ::std::max(item.width() * currentScale, 1.0);
decltype(top) h = (selectedItemsWasPainted && itemBlock.expanded && w > 20) ? ::profiler_gui::GRAPHICS_ROW_SIZE : item.totalHeight; decltype(top) h = (!itemBlock.expanded || (w < NARROW_ITEM_WIDTH && EASY_GLOBALS.hide_narrow_children)) ? item.totalHeight : ::profiler_gui::GRAPHICS_ROW_SIZE;
auto dh = top + h - visibleBottom; auto dh = top + h - visibleBottom;
if (dh < h) if (dh < h)
@ -405,7 +439,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
rect.setRect(x, top, w, h); rect.setRect(x, top, w, h);
_painter->drawRect(rect); _painter->drawRect(rect);
if (!selectedItemsWasPainted && w > 20) if (!selectedItemsWasPainted && w > NARROW_ITEM_WIDTH)
{ {
// Draw text----------------------------------- // Draw text-----------------------------------
// calculating text coordinates // calculating text coordinates
@ -492,8 +526,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
left = prevRight; left = prevRight;
} }
if (width < 2) if (width < MIN_ITEM_WIDTH)
width = 2; width = MIN_ITEM_WIDTH;
const bool self_thread = item.node->id() != 0 && EASY_GLOBALS.profiler_blocks.find(item.node->id()) != EASY_GLOBALS.profiler_blocks.end(); const bool self_thread = item.node->id() != 0 && EASY_GLOBALS.profiler_blocks.find(item.node->id()) != EASY_GLOBALS.profiler_blocks.end();
::profiler::color_t color = 0; ::profiler::color_t color = 0;
@ -516,7 +550,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
rect.setRect(left, top, width, h); rect.setRect(left, top, width, h);
_painter->drawRect(rect); _painter->drawRect(rect);
prevRight = left + width; prevRight = left + width + MIN_SYNC_SPACING;
} }
} }
} }
@ -725,7 +759,7 @@ const ::profiler_gui::EasyBlockItem* EasyGraphicsItem::intersect(const QPointF&
} }
const auto w = item.width() * currentScale; const auto w = item.width() * currentScale;
if (i == levelIndex || w < 20 || !easyBlock(item.block).expanded) if (i == levelIndex || (w < NARROW_ITEM_WIDTH && EASY_GLOBALS.hide_narrow_children) || !easyBlock(item.block).expanded)
{ {
return &item; return &item;
} }

View File

@ -51,6 +51,7 @@ namespace profiler_gui {
, enable_event_indicators(true) , enable_event_indicators(true)
, enable_statistics(true) , enable_statistics(true)
, draw_graphics_items_borders(true) , draw_graphics_items_borders(true)
, hide_narrow_children(true)
, display_only_relevant_stats(true) , display_only_relevant_stats(true)
, collapse_items_on_tree_close(false) , collapse_items_on_tree_close(false)
, all_items_expanded_by_default(true) , all_items_expanded_by_default(true)

View File

@ -101,6 +101,7 @@ namespace profiler_gui {
bool enable_event_indicators; ///< Enable event indicators painting (These are narrow rectangles at the bottom of each thread) bool enable_event_indicators; ///< Enable event indicators painting (These are narrow rectangles at the bottom of each thread)
bool enable_statistics; ///< Enable gathering and using statistics (Disable if you want to consume less memory) bool enable_statistics; ///< Enable gathering and using statistics (Disable if you want to consume less memory)
bool draw_graphics_items_borders; ///< Draw borders for graphics blocks or not bool draw_graphics_items_borders; ///< Draw borders for graphics blocks or not
bool hide_narrow_children; ///< Hide children for narrow graphics blocks
bool display_only_relevant_stats; ///< Display only relevant information in ProfTreeWidget (excludes min, max, average times if there are only 1 calls number) 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 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 bool all_items_expanded_by_default; ///< Expand all items after file is opened

View File

@ -1,20 +1,23 @@
logo.svg - Icon made by Freepik from www.flaticon.com logo.svg - Icon made by Freepik from www.flaticon.com
off.svg - Icon made by Freepik from www.flaticon.com off.svg - Icon made by Freepik from www.flaticon.com
open-folder.svg - Icon made by Freepik from www.flaticon.com open-folder.svg - Icon made by Freepik from www.flaticon.com
reload.svg - Icon made by Freepik from www.flaticon.com open-folder2.svg - Icon made by Freepik from www.flaticon.com
expand.svg - Icon made by Freepik from www.flaticon.com reload-folder2.svg - Icon made by Freepik from www.flaticon.com
collapse.svg - Icon made by Freepik from www.flaticon.com reload.svg - Icon made by Freepik from www.flaticon.com
colors.svg - Icon made by Freepik from www.flaticon.com expand.svg - Icon made by Freepik from www.flaticon.com
colors-black.svg - Icon made by Freepik from www.flaticon.com collapse.svg - Icon made by Freepik from www.flaticon.com
save.svg - Icon made by Freepik from www.flaticon.com colors.svg - Icon made by Freepik from www.flaticon.com
statistics.svg - Icon made by Freepik from www.flaticon.com colors-black.svg - Icon made by Freepik from www.flaticon.com
statistics2.svg - Icon made by Freepik from www.flaticon.com save.svg - Icon made by Freepik from www.flaticon.com
lan.svg - Icon made by Freepik from www.flaticon.com statistics.svg - Icon made by Freepik from www.flaticon.com
lan_on.svg - Icon made by Freepik from www.flaticon.com statistics2.svg - Icon made by Freepik from www.flaticon.com
wifi.svg - Icon made by Freepik from www.flaticon.com lan.svg - Icon made by Freepik from www.flaticon.com
wifi_on.svg - Icon made by Freepik from www.flaticon.com lan_on.svg - Icon made by Freepik from www.flaticon.com
play.svg - Icon made by Google from www.flaticon.com wifi.svg - Icon made by Freepik from www.flaticon.com
delete.svg - Icon made by Freepik from www.flaticon.com wifi_on.svg - Icon made by Freepik from www.flaticon.com
list.svg - Icon made by Freepik from www.flaticon.com play.svg - Icon made by Google from www.flaticon.com
search-prev.svg - Icon made by Freepik from www.flaticon.com delete.svg - Icon made by Freepik from www.flaticon.com
search-next.svg - Icon made by Freepik from www.flaticon.com list.svg - Icon made by Freepik from www.flaticon.com
search-prev.svg - Icon made by Freepik from www.flaticon.com
search-next.svg - Icon made by Freepik from www.flaticon.com
settings.svg - Icon made by Freepik from www.flaticon.com

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 247.355 247.355" style="enable-background:new 0 0 247.355 247.355;" xml:space="preserve">
<path style="fill:#212121;" d="M181.751,79.678h64.049c0.617,0,0.995,0.275,1.204,0.506c0.27,0.297,0.385,0.66,0.344,1.078l-14.7,147.766
c-0.086,0.863-0.824,1.65-1.548,1.65H15.792c-0.748,0-1.44-0.667-1.543-1.486L0.013,115.176c-0.05-0.396,0.041-0.719,0.278-0.986
c0.168-0.191,0.557-0.512,1.265-0.512h151.291c6.107,0,11.713-3.423,14.639-8.948l12.891-24.474
C180.653,79.734,181.429,79.678,181.751,79.678z"/>
<path style="fill:#f44336;" d="M152.847,98.678c0.513,0,1.077-0.392,1.375-0.953l12.891-24.474
c2.803-5.294,8.409-8.573,14.638-8.573h54.594v-16.75c0-8.837-5.87-15.25-14.417-15.25H91.428c-0.536-0.009-1.569-0.809-1.752-1.342
c-0.001-0.113-0.005-0.227-0.011-0.338c-0.304-8.467-6.278-14.32-14.738-14.32h-48.5c-9.393,0-17.083,6.479-17.083,14.75v67.25
H152.847z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 247.355 247.355" style="enable-background:new 0 0 247.355 247.355;" xml:space="preserve">
<path style="fill:#f44336;" d="M9.344,98.678v-67.25c0-8.271,7.69-14.75,17.083-14.75h48.5c8.46,0,14.435,5.854,14.738,14.32
c0.006,0.111,0.01,0.225,0.011,0.338c0.183,0.533,1.216,1.333,1.752,1.342h130.499c8.547,0,14.417,6.413,14.417,15.25v16.75h-54.594
c-6.229,0-11.835,3.279-14.638,8.573l-12.891,24.474c-0.298,0.562-0.862,0.953-1.375,0.953H9.344z"/>
<path style="fill:#212121;" d="M247.347,81.262l-14.7,147.766
c-0.086,0.863-0.824,1.65-1.548,1.65H15.792c-0.748,0-1.44-0.667-1.543-1.486L0.013,115.176c-0.05-0.396,0.041-0.719,0.278-0.986
c0.168-0.191,0.557-0.512,1.265-0.512h151.291c6.107,0,11.713-3.423,14.639-8.948l12.891-24.474
c0.276-0.521,1.053-0.578,1.374-0.578h64.049c0.617,0,0.995,0.275,1.204,0.506C247.273,80.48,247.388,80.844,247.347,81.262z"/>
<path style="fill:#f44336;" d="M203.177,188.998c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5c0,8.336-6.781,15.117-15.116,15.117
c-4.563,0-8.651-2.041-11.425-5.247c2.581,0.161,5.176-1.011,6.714-3.319c2.298-3.446,1.366-8.103-2.08-10.4l-11.466-7.645
c-2.52-1.68-5.801-1.68-8.32,0l-11.467,7.645c-3.446,2.298-4.378,6.954-2.08,10.4c1.445,2.168,3.823,3.341,6.247,3.341
c1.43,0,2.875-0.408,4.153-1.261l0.734-0.489c3.561,12.662,15.205,21.976,28.99,21.976
C189.667,219.115,203.177,205.604,203.177,188.998z M212.917,154.81c-2.298-3.446-6.954-4.377-10.4-2.08l-0.733,0.489
c-3.562-12.662-15.205-21.975-28.99-21.975c-16.606,0-30.117,13.511-30.117,30.117c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5
c0-8.336,6.781-15.117,15.117-15.117c4.563,0,8.651,2.041,11.425,5.248c-2.582-0.161-5.177,1.012-6.715,3.319
c-2.298,3.446-1.366,8.103,2.08,10.4l11.467,7.645c1.26,0.84,2.71,1.26,4.16,1.26s2.9-0.42,4.16-1.26l11.466-7.645
C214.284,162.913,215.215,158.257,212.917,154.81z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,43 +1,74 @@
<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg
viewBox="0 0 284.515 284.515" style="enable-background:new 0 0 284.515 284.515;" xml:space="preserve"> xmlns:dc="http://purl.org/dc/elements/1.1/"
<g> xmlns:cc="http://creativecommons.org/ns#"
<path style="fill:#212121;" d="M282.166,27.382L259.88,2.937C258.174,1.066,255.76,0,253.229,0h-39.936H71.221H9C4.03,0,0,4.029,0,9v266.515 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
c0,4.971,4.029,9,9,9h266.514c4.971,0,9-4.029,9-9V33.446C284.514,31.203,283.676,29.04,282.166,27.382z M204.293,18v69.443 xmlns:svg="http://www.w3.org/2000/svg"
h-35.951V18H204.293z M150.342,18v69.443H80.221V18H150.342z M220.581,266.515H63.934V159.44h156.646V266.515z M266.514,266.515 xmlns="http://www.w3.org/2000/svg"
h-27.934V150.44c0-4.971-4.029-9-9-9H54.934c-4.971,0-9,4.029-9,9v116.074H18V18h44.221v78.443c0,4.971,4.029,9,9,9h142.072 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
c4.971,0,9-4.029,9-9V18h26.962l17.259,18.933V266.515z"/> xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
</g> version="1.1"
<g> id="Layer_1"
</g> x="0px"
<g> y="0px"
</g> viewBox="0 0 512 512"
<g> style="enable-background:new 0 0 512 512;"
</g> xml:space="preserve"
<g> inkscape:version="0.91 r13725"
</g> sodipodi:docname="save.svg"><metadata
<g> id="metadata49"><rdf:RDF><cc:Work
</g> rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
<g> rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
</g> id="defs47" /><sodipodi:namedview
<g> pagecolor="#ffffff"
</g> bordercolor="#666666"
<g> borderopacity="1"
</g> objecttolerance="10"
<g> gridtolerance="10"
</g> guidetolerance="10"
<g> inkscape:pageopacity="0"
</g> inkscape:pageshadow="2"
<g> inkscape:window-width="1293"
</g> inkscape:window-height="921"
<g> id="namedview45"
</g> showgrid="false"
<g> inkscape:zoom="0.4609375"
</g> inkscape:cx="256"
<g> inkscape:cy="256"
</g> inkscape:window-x="0"
<g> inkscape:window-y="0"
</g> inkscape:window-maximized="0"
</svg> inkscape:current-layer="Layer_1" /><g
id="g3"
transform="matrix(0.87890453,0,0,0.87890625,30,32)"><g
id="g5"><g
id="g7"><path
style="fill:#212121"
d="M 506.513,98.709 413.291,5.486 C 409.78,1.974 405.014,0 400.047,0 L 385.77,0 c -3.448,0 -6.244,2.796 -6.244,6.244 l 0,151.114 c 0,10.345 -8.387,18.732 -18.732,18.732 l -209.598,0 c -10.345,0 -18.732,-8.387 -18.732,-18.732 l 0,-151.114 C 132.464,2.796 129.668,0 126.22,0 L 18.732,0 C 8.387,0 0,8.387 0,18.732 L 0,493.269 C 0,503.613 8.387,512 18.732,512 l 474.537,0 c 10.345,0 18.732,-8.387 18.732,-18.732 l 0,-381.314 C 512,106.987 510.027,102.221 506.513,98.709 Z M 400.554,410.226 c 0,10.345 -8.387,18.732 -18.732,18.732 l -251.644,0 c -10.345,0 -18.732,-8.387 -18.732,-18.732 l 0,-147.132 c 0,-10.345 8.387,-18.732 18.732,-18.732 l 251.644,0 c 10.345,0 18.732,8.387 18.732,18.732 l 0,147.132 z"
id="path9"
inkscape:connector-curvature="0" /><path
style="fill:#f44336"
d="m 176.172,126.138 159.647,0 c 3.449,0 6.244,-2.796 6.244,-6.244 l 0,-113.65 C 342.063,2.796 339.267,0 335.819,0 L 176.172,0 c -3.448,0 -6.244,2.796 -6.244,6.244 l 0,113.65 c 0,3.448 2.796,6.244 6.244,6.244 z M 275.346,46.27 c 0,-10.345 8.387,-18.732 18.732,-18.732 10.345,0 18.732,8.387 18.732,18.732 l 0,33.598 c 0,10.345 -8.387,18.732 -18.732,18.732 -10.345,0 -18.732,-8.387 -18.732,-18.732 l 0,-33.598 z"
id="path11"
inkscape:connector-curvature="0" /><path
style="fill:#f44336"
d="m 318.413,317.93 -124.827,0 c -10.345,0 -18.732,8.387 -18.732,18.732 0,10.345 8.387,18.732 18.732,18.732 l 124.828,0 c 10.345,0 18.73,-8.387 18.73,-18.732 0,-10.345 -8.386,-18.732 -18.731,-18.732 z"
id="path13"
inkscape:connector-curvature="0" /></g></g></g><g
id="g15" /><g
id="g17" /><g
id="g19" /><g
id="g21" /><g
id="g23" /><g
id="g25" /><g
id="g27" /><g
id="g29" /><g
id="g31" /><g
id="g33" /><g
id="g35" /><g
id="g37" /><g
id="g39" /><g
id="g41" /><g
id="g43" /></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="932.179px" height="932.179px" viewBox="0 0 932.179 932.179" style="enable-background:new 0 0 932.179 932.179;"
xml:space="preserve">
<g>
<path style="fill:#212121;" d="M61.2,341.538c4.9,16.8,11.7,33,20.3,48.2l-24.5,30.9c-8,10.1-7.1,24.5,1.9,33.6l42.2,42.2c9.1,9.1,23.5,9.899,33.6,1.899
l30.7-24.3c15.8,9.101,32.6,16.2,50.1,21.2l4.6,39.5c1.5,12.8,12.3,22.4,25.1,22.4h59.7c12.8,0,23.6-9.601,25.1-22.4l4.4-38.1
c18.8-4.9,36.8-12.2,53.7-21.7l29.7,23.5c10.1,8,24.5,7.1,33.6-1.9l42.2-42.2c9.1-9.1,9.9-23.5,1.9-33.6l-23.1-29.3
c9.6-16.601,17.1-34.3,22.1-52.8l35.6-4.1c12.801-1.5,22.4-12.3,22.4-25.1v-59.7c0-12.8-9.6-23.6-22.4-25.1l-35.1-4.1
c-4.801-18.3-12-35.8-21.199-52.2l21.6-27.3c8-10.1,7.1-24.5-1.9-33.6l-42.1-42.1c-9.1-9.1-23.5-9.9-33.6-1.9l-26.5,21
c-17.2-10.1-35.601-17.8-54.9-23l-4-34.3c-1.5-12.8-12.3-22.4-25.1-22.4h-59.7c-12.8,0-23.6,9.6-25.1,22.4l-4,34.3
c-19.8,5.3-38.7,13.3-56.3,23.8l-27.5-21.8c-10.1-8-24.5-7.1-33.6,1.9l-42.2,42.2c-9.1,9.1-9.9,23.5-1.9,33.6l23,29.1
c-9.2,16.6-16.2,34.3-20.8,52.7l-36.8,4.2c-12.8,1.5-22.4,12.3-22.4,25.1v59.7c0,12.8,9.6,23.6,22.4,25.1L61.2,341.538z
M277.5,180.038c54.4,0,98.7,44.3,98.7,98.7s-44.3,98.7-98.7,98.7c-54.399,0-98.7-44.3-98.7-98.7S223.1,180.038,277.5,180.038z"/>
<path style="fill:#f44336;" d="M867.699,356.238l-31.5-26.6c-9.699-8.2-24-7.8-33.199,0.9l-17.4,16.3c-14.699-7.1-30.299-12.1-46.4-15l-4.898-24
c-2.5-12.4-14-21-26.602-20l-41.1,3.5c-12.6,1.1-22.5,11.4-22.9,24.1l-0.799,24.4c-15.801,5.7-30.701,13.5-44.301,23.3
l-20.799-13.8c-10.602-7-24.701-5-32.9,4.7l-26.6,31.7c-8.201,9.7-7.801,24,0.898,33.2l18.201,19.399
c-6.301,14.2-10.801,29.101-13.4,44.4l-26,5.3c-12.4,2.5-21,14-20,26.601l3.5,41.1c1.1,12.6,11.4,22.5,24.1,22.9l28.1,0.899
c5.102,13.4,11.801,26.101,19.9,38l-15.699,23.7c-7,10.6-5,24.7,4.699,32.9l31.5,26.6c9.701,8.2,24,7.8,33.201-0.9l20.6-19.3
c13.5,6.3,27.699,11,42.299,13.8l5.701,28.2c2.5,12.4,14,21,26.6,20l41.1-3.5c12.6-1.1,22.5-11.399,22.9-24.1l0.9-27.601
c15-5.3,29.199-12.5,42.299-21.399l22.701,15c10.6,7,24.699,5,32.9-4.7l26.6-31.5c8.199-9.7,7.799-24-0.9-33.2l-18.301-19.399
c6.701-14.2,11.602-29.2,14.4-44.601l25-5.1c12.4-2.5,21-14,20-26.601l-3.5-41.1c-1.1-12.6-11.4-22.5-24.1-22.9l-25.1-0.8
c-5.201-14.6-12.201-28.399-20.9-41.2l13.699-20.6C879.4,378.638,877.4,364.438,867.699,356.238z M712.801,593.837
c-44.4,3.801-83.602-29.3-87.301-73.699c-3.801-44.4,29.301-83.601,73.699-87.301c44.4-3.8,83.602,29.301,87.301,73.7
C790.301,550.938,757.199,590.138,712.801,593.837z"/>
<path style="fill:#212121;" d="M205,704.438c-12.6,1.3-22.3,11.899-22.4,24.6l-0.3,25.3c-0.2,12.7,9.2,23.5,21.8,25.101l18.6,2.399
c3.1,11.301,7.5,22.101,13.2,32.301l-12,14.8c-8,9.899-7.4,24.1,1.5,33.2l17.7,18.1c8.9,9.1,23.1,10.1,33.2,2.3l14.899-11.5
c10.5,6.2,21.601,11.101,33.2,14.5l2,19.2c1.3,12.6,11.9,22.3,24.6,22.4l25.301,0.3c12.699,0.2,23.5-9.2,25.1-21.8l2.3-18.2
c12.601-3.101,24.601-7.8,36-14l14,11.3c9.9,8,24.101,7.4,33.201-1.5l18.1-17.7c9.1-8.899,10.1-23.1,2.301-33.2L496.6,818.438
c6.6-11,11.701-22.7,15.201-35l16.6-1.7c12.6-1.3,22.299-11.9,22.4-24.6l0.299-25.301c0.201-12.699-9.199-23.5-21.799-25.1
l-16.201-2.1c-3.1-12.2-7.699-24-13.699-35l10.1-12.4c8-9.9,7.4-24.1-1.5-33.2l-17.699-18.1c-8.9-9.101-23.102-10.101-33.201-2.3
l-12.101,9.3c-11.399-6.9-23.6-12.2-36.399-15.8l-1.601-15.7c-1.3-12.601-11.899-22.3-24.6-22.4l-25.3-0.3
c-12.7-0.2-23.5,9.2-25.101,21.8l-2,15.601c-13.199,3.399-25.899,8.6-37.699,15.399l-12.5-10.2c-9.9-8-24.101-7.399-33.201,1.5
l-18.2,17.801c-9.1,8.899-10.1,23.1-2.3,33.199l10.7,13.801c-6.2,11-11.1,22.699-14.3,35L205,704.438z M368.3,675.837
c36.3,0.4,65.399,30.301,65,66.601c-0.4,36.3-30.301,65.399-66.601,65c-36.3-0.4-65.399-30.3-65-66.601
C302.1,704.538,332,675.438,368.3,675.837z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -53,11 +53,14 @@
#include <QSignalBlocker> #include <QSignalBlocker>
#include <QDebug> #include <QDebug>
#include <QToolBar> #include <QToolBar>
#include <QToolButton>
#include <QWidgetAction>
#include <QMessageBox> #include <QMessageBox>
#include <QLineEdit> #include <QLineEdit>
#include <QLabel> #include <QLabel>
#include <QDialog> #include <QDialog>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QFile>
#include "main_window.h" #include "main_window.h"
#include "blocks_tree_widget.h" #include "blocks_tree_widget.h"
@ -77,10 +80,11 @@
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
const int LOADER_TIMER_INTERVAL = 40; const int LOADER_TIMER_INTERVAL = 40;
const auto NETWORK_CACHE_FILE = "easy_profiler_stream.cache";
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
EasyMainWindow::EasyMainWindow() : Parent() EasyMainWindow::EasyMainWindow() : Parent(), m_lastAddress("127.0.0.1"), m_lastPort(::profiler::DEFAULT_PORT)
{ {
{ QIcon icon(":/logo"); if (!icon.isNull()) QApplication::setWindowIcon(icon); } { QIcon icon(":/logo"); if (!icon.isNull()) QApplication::setWindowIcon(icon); }
@ -118,9 +122,27 @@ EasyMainWindow::EasyMainWindow() : Parent()
addDockWidget(Qt::BottomDockWidgetArea, m_descTreeWidget); addDockWidget(Qt::BottomDockWidgetArea, m_descTreeWidget);
#endif #endif
auto toolbar = addToolBar("MainToolBar");
toolbar->setObjectName("ProfilerGUI_MainToolBar"); loadSettings();
toolbar->addAction(QIcon(":/Delete"), tr("Clear all"), this, SLOT(onDeleteClicked(bool)));
auto toolbar = addToolBar("FileToolbar");
toolbar->setObjectName("ProfilerGUI_FileToolbar");
toolbar->setContentsMargins(1, 0, 1, 0);
toolbar->addAction(QIcon(":/Open"), tr("Open"), this, SLOT(onOpenFileClicked(bool)));
toolbar->addAction(QIcon(":/Reopen"), tr("Reload last file"), this, SLOT(onReloadFileClicked(bool)));
m_saveAction = toolbar->addAction(QIcon(":/Save"), tr("Save"), this, SLOT(onSaveFileClicked(bool)));
m_deleteAction = toolbar->addAction(QIcon(":/Delete"), tr("Clear all"), this, SLOT(onDeleteClicked(bool)));
m_saveAction->setEnabled(false);
m_deleteAction->setEnabled(false);
toolbar = addToolBar("ProfileToolbar");
toolbar->setObjectName("ProfilerGUI_ProfileToolbar");
toolbar->setContentsMargins(1, 0, 1, 0);
toolbar->addAction(QIcon(":/List"), tr("Blocks"), this, SLOT(onEditBlocksClicked(bool))); toolbar->addAction(QIcon(":/List"), tr("Blocks"), this, SLOT(onEditBlocksClicked(bool)));
m_captureAction = toolbar->addAction(QIcon(":/Start"), tr("Capture"), this, SLOT(onCaptureClicked(bool))); m_captureAction = toolbar->addAction(QIcon(":/Start"), tr("Capture"), this, SLOT(onCaptureClicked(bool)));
@ -129,18 +151,22 @@ EasyMainWindow::EasyMainWindow() : Parent()
toolbar->addSeparator(); toolbar->addSeparator();
m_connectAction = toolbar->addAction(QIcon(":/Connection"), tr("Connect"), this, SLOT(onConnectClicked(bool))); m_connectAction = toolbar->addAction(QIcon(":/Connection"), tr("Connect"), this, SLOT(onConnectClicked(bool)));
toolbar->addWidget(new QLabel(" IP:")); auto lbl = new QLabel("IP:", toolbar);
lbl->setContentsMargins(5, 0, 1, 0);
toolbar->addWidget(lbl);
m_ipEdit = new QLineEdit(); m_ipEdit = new QLineEdit();
QRegExp rx("^0*(2(5[0-5]|[0-4]\\d)|1?\\d{1,2})(\\.0*(2(5[0-5]|[0-4]\\d)|1?\\d{1,2})){3}$"); QRegExp rx("^0*(2(5[0-5]|[0-4]\\d)|1?\\d{1,2})(\\.0*(2(5[0-5]|[0-4]\\d)|1?\\d{1,2})){3}$");
m_ipEdit->setValidator(new QRegExpValidator(rx, m_ipEdit)); m_ipEdit->setValidator(new QRegExpValidator(rx, m_ipEdit));
m_ipEdit->setText("127.0.0.1"); m_ipEdit->setText(m_lastAddress);
m_ipEdit->setFixedWidth(m_ipEdit->fontMetrics().width(QString("255.255.255.255")) + 20); m_ipEdit->setFixedWidth(m_ipEdit->fontMetrics().width(QString("255.255.255.255")) + 20);
toolbar->addWidget(m_ipEdit); toolbar->addWidget(m_ipEdit);
toolbar->addWidget(new QLabel(" Port:")); lbl = new QLabel("Port:", toolbar);
lbl->setContentsMargins(5, 0, 1, 0);
toolbar->addWidget(lbl);
m_portEdit = new QLineEdit(); m_portEdit = new QLineEdit();
m_portEdit->setValidator(new QIntValidator(1, 65535, m_portEdit)); m_portEdit->setValidator(new QIntValidator(1, 65535, m_portEdit));
m_portEdit->setText(QString::number(::profiler::DEFAULT_PORT)); m_portEdit->setText(QString::number(m_lastPort));
m_portEdit->setFixedWidth(m_portEdit->fontMetrics().width(QString("000000")) + 10); m_portEdit->setFixedWidth(m_portEdit->fontMetrics().width(QString("000000")) + 10);
toolbar->addWidget(m_portEdit); toolbar->addWidget(m_portEdit);
@ -148,86 +174,23 @@ EasyMainWindow::EasyMainWindow() : Parent()
connect(m_portEdit, &QLineEdit::returnPressed, [this](){ onConnectClicked(true); }); connect(m_portEdit, &QLineEdit::returnPressed, [this](){ onConnectClicked(true); });
loadSettings();
if (!m_lastAddress.isEmpty())
m_ipEdit->setText(m_lastAddress);
if (m_lastPort != 0)
m_portEdit->setText(QString::number(m_lastPort));
toolbar = addToolBar("SetupToolbar");
toolbar->setObjectName("ProfilerGUI_SetupToolbar");
toolbar->setContentsMargins(1, 0, 1, 0);
auto menu = menuBar()->addMenu("&File"); toolbar->addAction(QIcon(":/Expand"), "Expand all", this, SLOT(onExpandAllClicked(bool)));
menu->addAction(QIcon(":/Open"), "&Open", this, SLOT(onOpenFileClicked(bool))); toolbar->addAction(QIcon(":/Collapse"), "Collapse all", this, SLOT(onCollapseAllClicked(bool)));
menu->addAction(QIcon(":/Reload"), "&Reload", this, SLOT(onReloadFileClicked(bool)));
menu->addSeparator();
menu->addAction(QIcon(":/Exit"), "&Exit", this, SLOT(onExitClicked(bool)));
toolbar->addSeparator();
auto menu = new QMenu("Settings", this);
QToolButton* toolButton = new QToolButton(toolbar);
toolButton->setIcon(QIcon(":/Settings"));
toolButton->setMenu(menu);
toolButton->setPopupMode(QToolButton::InstantPopup);
toolbar->addWidget(toolButton);
auto action = menu->addAction("Statistics enabled");
menu = menuBar()->addMenu("&View");
menu->addAction(QIcon(":/Expand"), "Expand all", this, SLOT(onExpandAllClicked(bool)));
menu->addAction(QIcon(":/Collapse"), "Collapse all", this,SLOT(onCollapseAllClicked(bool)));
menu->addSeparator();
auto action = menu->addAction("Draw items' borders");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
connect(action, &QAction::triggered, this, &This::onDrawBordersChanged);
action = menu->addAction("Collapse items on tree reset");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.collapse_items_on_tree_close);
connect(action, &QAction::triggered, this, &This::onCollapseItemsAfterCloseChanged);
action = menu->addAction("Expand all on file open");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.all_items_expanded_by_default);
connect(action, &QAction::triggered, this, &This::onAllItemsExpandedByDefaultChange);
action = menu->addAction("Bind scene and tree expand");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange);
action = menu->addAction("Draw event indicators");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.enable_event_indicators);
connect(action, &QAction::triggered, this, &This::onEventIndicatorsChange);
menu->addSeparator();
auto submenu = menu->addMenu("Chronometer text");
auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true);
action = new QAction("At top", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Top));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
action = new QAction("At center", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Center));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
action = new QAction("At bottom", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Bottom));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
menu = menuBar()->addMenu("&Settings");
action = menu->addAction("Statistics enabled");
action->setCheckable(true); action->setCheckable(true);
action->setChecked(EASY_GLOBALS.enable_statistics); action->setChecked(EASY_GLOBALS.enable_statistics);
connect(action, &QAction::triggered, this, &This::onEnableDisableStatistics); connect(action, &QAction::triggered, this, &This::onEnableDisableStatistics);
@ -244,8 +207,69 @@ EasyMainWindow::EasyMainWindow() : Parent()
SET_ICON(action, ":/Stats-off"); SET_ICON(action, ":/Stats-off");
} }
menu->addSeparator(); menu->addSeparator();
submenu = menu->addMenu("&Remote"); auto submenu = menu->addMenu("View");
action = submenu->addAction("Draw items' borders");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
connect(action, &QAction::triggered, this, &This::onDrawBordersChanged);
action = submenu->addAction("Hide narrow children");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.hide_narrow_children);
connect(action, &QAction::triggered, this, &This::onHideNarrowChildrenChanged);
action = submenu->addAction("Collapse items on tree reset");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.collapse_items_on_tree_close);
connect(action, &QAction::triggered, this, &This::onCollapseItemsAfterCloseChanged);
action = submenu->addAction("Expand all on file open");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.all_items_expanded_by_default);
connect(action, &QAction::triggered, this, &This::onAllItemsExpandedByDefaultChange);
action = submenu->addAction("Bind scene and tree expand");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange);
action = submenu->addAction("Draw event indicators");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.enable_event_indicators);
connect(action, &QAction::triggered, this, &This::onEventIndicatorsChange);
submenu->addSeparator();
auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true);
action = new QAction("Chrono text at top", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Top));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
action = new QAction("Chrono text at center", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Center));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
action = new QAction("Chrono text at bottom", actionGroup);
action->setCheckable(true);
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Bottom));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
submenu = menu->addMenu("Remote");
m_eventTracingEnableAction = submenu->addAction("Event tracing enabled"); m_eventTracingEnableAction = submenu->addAction("Event tracing enabled");
m_eventTracingEnableAction->setCheckable(true); m_eventTracingEnableAction->setCheckable(true);
m_eventTracingEnableAction->setEnabled(false); m_eventTracingEnableAction->setEnabled(false);
@ -257,13 +281,13 @@ EasyMainWindow::EasyMainWindow() : Parent()
m_eventTracingPriorityAction->setEnabled(false); m_eventTracingPriorityAction->setEnabled(false);
connect(m_eventTracingPriorityAction, &QAction::triggered, this, &This::onEventTracingPriorityChange); connect(m_eventTracingPriorityAction, &QAction::triggered, this, &This::onEventTracingPriorityChange);
menu->addSeparator();
submenu = menu->addMenu("&Encoding"); submenu = menu->addMenu("Encoding");
actionGroup = new QActionGroup(this); actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true); actionGroup->setExclusive(true);
auto default_codec_mib = QTextCodec::codecForLocale()->mibEnum(); auto default_codec_mib = QTextCodec::codecForLocale()->mibEnum();
foreach (int mib, QTextCodec::availableMibs()) foreach(int mib, QTextCodec::availableMibs())
{ {
auto codec = QTextCodec::codecForMib(mib)->name(); auto codec = QTextCodec::codecForMib(mib)->name();
@ -352,7 +376,77 @@ void EasyMainWindow::onReloadFileClicked(bool)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void EasyMainWindow::onDeleteClicked(bool) void EasyMainWindow::onSaveFileClicked(bool)
{
if (m_serializedBlocks.empty())
return;
const auto i = m_lastFile.lastIndexOf(QChar('/'));
const auto j = m_lastFile.lastIndexOf(QChar('\\'));
auto k = ::std::max(i, j);
QString dir;
if (k > 0)
dir = m_lastFile.mid(0, ++k);
auto filename = QFileDialog::getSaveFileName(this, "Save profiler log", dir, "Profiler Log File (*.prof);;All Files (*.*)");
if (!filename.isEmpty())
{
bool inOk = false, outOk = false;
int8_t retry1 = -1;
while (++retry1 < 4)
{
::std::ifstream inFile(m_bNetworkFileRegime ? NETWORK_CACHE_FILE : m_lastFile.toStdString().c_str(), ::std::fstream::binary);
if (!inFile.is_open())
{
::std::this_thread::sleep_for(::std::chrono::milliseconds(500));
continue;
}
inOk = true;
int8_t retry2 = -1;
while (++retry2 < 4)
{
::std::ofstream outFile(filename.toStdString(), ::std::fstream::binary);
if (!outFile.is_open())
{
::std::this_thread::sleep_for(::std::chrono::milliseconds(500));
continue;
}
outFile << inFile.rdbuf();
outOk = true;
break;
}
break;
}
if (outOk)
{
if (m_bNetworkFileRegime)
QFile::remove(QString(NETWORK_CACHE_FILE));
m_lastFile = filename;
m_bNetworkFileRegime = false;
}
else if (inOk)
{
QMessageBox::warning(this, "Warning", "Can not open destination file.\nSaving incomplete.", QMessageBox::Close);
}
else
{
if (m_bNetworkFileRegime)
QMessageBox::warning(this, "Warning", "Can not open network cache file.\nSaving incomplete.", QMessageBox::Close);
else
QMessageBox::warning(this, "Warning", "Can not open source file.\nSaving incomplete.", QMessageBox::Close);
}
}
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::clear()
{ {
static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true); static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->clear(); static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->clear();
@ -371,6 +465,18 @@ void EasyMainWindow::onDeleteClicked(bool)
m_serializedBlocks.clear(); m_serializedBlocks.clear();
m_serializedDescriptors.clear(); m_serializedDescriptors.clear();
m_saveAction->setEnabled(false);
m_deleteAction->setEnabled(false);
m_bNetworkFileRegime = false;
}
void EasyMainWindow::onDeleteClicked(bool)
{
auto button = QMessageBox::question(this, "Clear all profiled data", "All profiled data is going to be deleted!\nContinue?", QMessageBox::Yes, QMessageBox::No);
if (button == QMessageBox::Yes)
clear();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -433,6 +539,12 @@ void EasyMainWindow::onDrawBordersChanged(bool _checked)
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->scene()->update(); static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->scene()->update();
} }
void EasyMainWindow::onHideNarrowChildrenChanged(bool _checked)
{
EASY_GLOBALS.hide_narrow_children = _checked;
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->scene()->update();
}
void EasyMainWindow::onCollapseItemsAfterCloseChanged(bool _checked) void EasyMainWindow::onCollapseItemsAfterCloseChanged(bool _checked)
{ {
EASY_GLOBALS.collapse_items_on_tree_close = _checked; EASY_GLOBALS.collapse_items_on_tree_close = _checked;
@ -551,6 +663,10 @@ void EasyMainWindow::loadSettings()
if (!flag.isNull()) if (!flag.isNull())
EASY_GLOBALS.draw_graphics_items_borders = flag.toBool(); EASY_GLOBALS.draw_graphics_items_borders = flag.toBool();
flag = settings.value("hide_narrow_children");
if (!flag.isNull())
EASY_GLOBALS.hide_narrow_children = flag.toBool();
flag = settings.value("collapse_items_on_tree_close"); flag = settings.value("collapse_items_on_tree_close");
if (!flag.isNull()) if (!flag.isNull())
EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool(); EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool();
@ -607,6 +723,7 @@ void EasyMainWindow::saveSettingsAndGeometry()
settings.setValue("port", (quint32)m_lastPort); settings.setValue("port", (quint32)m_lastPort);
settings.setValue("chrono_text_position", static_cast<int>(EASY_GLOBALS.chrono_text_position)); settings.setValue("chrono_text_position", static_cast<int>(EASY_GLOBALS.chrono_text_position));
settings.setValue("draw_graphics_items_borders", EASY_GLOBALS.draw_graphics_items_borders); settings.setValue("draw_graphics_items_borders", EASY_GLOBALS.draw_graphics_items_borders);
settings.setValue("hide_narrow_children", EASY_GLOBALS.hide_narrow_children);
settings.setValue("collapse_items_on_tree_close", EASY_GLOBALS.collapse_items_on_tree_close); 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("all_items_expanded_by_default", EASY_GLOBALS.all_items_expanded_by_default);
settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status); settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status);
@ -687,12 +804,14 @@ void EasyMainWindow::onFileReaderTimeout()
{ {
static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true); static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
::profiler::SerializedData serialized_blocks, serialized_descriptors; ::profiler::SerializedData serialized_blocks;
::profiler::SerializedData serialized_descriptors;
::profiler::descriptors_list_t descriptors; ::profiler::descriptors_list_t descriptors;
::profiler::blocks_t blocks; ::profiler::blocks_t blocks;
::profiler::thread_blocks_tree_t threads_map; ::profiler::thread_blocks_tree_t threads_map;
QString filename; QString filename;
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, filename); uint32_t descriptorsNumberInFile = 0;
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, descriptorsNumberInFile, filename);
if (threads_map.size() > 0xff) if (threads_map.size() > 0xff)
{ {
@ -703,10 +822,12 @@ void EasyMainWindow::onFileReaderTimeout()
qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed."; qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed.";
} }
if (m_reader.isFile()) m_bNetworkFileRegime = !m_reader.isFile();
if (!m_bNetworkFileRegime)
m_lastFile = ::std::move(filename); m_lastFile = ::std::move(filename);
m_serializedBlocks = ::std::move(serialized_blocks); m_serializedBlocks = ::std::move(serialized_blocks);
m_serializedDescriptors = ::std::move(serialized_descriptors); m_serializedDescriptors = ::std::move(serialized_descriptors);
m_descriptorsNumberInFile = descriptorsNumberInFile;
EASY_GLOBALS.selected_thread = 0; EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(EASY_GLOBALS.selected_block); ::profiler_gui::set_max(EASY_GLOBALS.selected_block);
EASY_GLOBALS.profiler_blocks.swap(threads_map); EASY_GLOBALS.profiler_blocks.swap(threads_map);
@ -728,6 +849,9 @@ void EasyMainWindow::onFileReaderTimeout()
#endif #endif
if (m_dialogDescTree != nullptr) if (m_dialogDescTree != nullptr)
m_dialogDescTree->build(); m_dialogDescTree->build();
m_saveAction->setEnabled(true);
m_deleteAction->setEnabled(true);
} }
else else
{ {
@ -803,7 +927,8 @@ void EasyFileReader::load(const QString& _filename)
m_isFile = true; m_isFile = true;
m_filename = _filename; m_filename = _filename;
m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { m_thread = ::std::move(::std::thread([this](bool _enableStatistics) {
m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors, m_descriptors, m_blocks, m_blocksTree, _enableStatistics, m_errorMessage), ::std::memory_order_release); m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors,
m_descriptors, m_blocks, m_blocksTree, m_descriptorsNumberInFile, _enableStatistics, m_errorMessage), ::std::memory_order_release);
m_progress.store(100, ::std::memory_order_release); m_progress.store(100, ::std::memory_order_release);
m_bDone.store(true, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release);
}, EASY_GLOBALS.enable_statistics)); }, EASY_GLOBALS.enable_statistics));
@ -817,7 +942,13 @@ void EasyFileReader::load(::std::stringstream& _stream)
m_filename.clear(); m_filename.clear();
m_stream.swap(_stream); m_stream.swap(_stream);
m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { m_thread = ::std::move(::std::thread([this](bool _enableStatistics) {
m_size.store(fillTreesFromStream(m_progress, m_stream, m_serializedBlocks, m_serializedDescriptors, m_descriptors, m_blocks, m_blocksTree, _enableStatistics, m_errorMessage), ::std::memory_order_release); ::std::ofstream cache_file(NETWORK_CACHE_FILE, ::std::fstream::binary);
if (cache_file.is_open()) {
cache_file << m_stream.str();
cache_file.close();
}
m_size.store(fillTreesFromStream(m_progress, m_stream, m_serializedBlocks, m_serializedDescriptors, m_descriptors,
m_blocks, m_blocksTree, m_descriptorsNumberInFile, _enableStatistics, m_errorMessage), ::std::memory_order_release);
m_progress.store(100, ::std::memory_order_release); m_progress.store(100, ::std::memory_order_release);
m_bDone.store(true, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release);
}, EASY_GLOBALS.enable_statistics)); }, EASY_GLOBALS.enable_statistics));
@ -837,14 +968,15 @@ void EasyFileReader::interrupt()
m_descriptors.clear(); m_descriptors.clear();
m_blocks.clear(); m_blocks.clear();
m_blocksTree.clear(); m_blocksTree.clear();
m_descriptorsNumberInFile = 0;
{ decltype(m_stream) dummy; dummy.swap(m_stream); } { decltype(m_stream) dummy; dummy.swap(m_stream); }
{ decltype(m_errorMessage) dummy; dummy.swap(m_errorMessage); } { decltype(m_errorMessage) dummy; dummy.swap(m_errorMessage); }
} }
void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors, void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree, ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks,
QString& _filename) ::profiler::thread_blocks_tree_t& _tree, uint32_t& _descriptorsNumberInFile, QString& _filename)
{ {
if (done()) if (done())
{ {
@ -854,6 +986,7 @@ void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profil
m_blocks.swap(_blocks); m_blocks.swap(_blocks);
m_blocksTree.swap(_tree); m_blocksTree.swap(_tree);
m_filename.swap(_filename); m_filename.swap(_filename);
_descriptorsNumberInFile = m_descriptorsNumberInFile;
} }
} }
@ -992,28 +1125,99 @@ void EasyMainWindow::onGetBlockDescriptionsClicked(bool)
if (m_listener.size() != 0) if (m_listener.size() != 0)
{ {
// Read descriptions from stream // Read descriptions from stream
decltype(EASY_GLOBALS.descriptors) descriptors; decltype(EASY_GLOBALS.descriptors) descriptors;
decltype(m_serializedDescriptors) serializedDescriptors; decltype(m_serializedDescriptors) serializedDescriptors;
::std::stringstream errorMessage; ::std::stringstream errorMessage;
if (readDescriptionsFromStream(m_listener.data(), serializedDescriptors, descriptors, errorMessage)) if (readDescriptionsFromStream(m_listener.data(), serializedDescriptors, descriptors, errorMessage))
{ {
if (EASY_GLOBALS.descriptors.size() > descriptors.size()) // Merge old and new descriptions
onDeleteClicked(true); // Clear all contents because new descriptors list conflicts with old one
EASY_GLOBALS.descriptors.swap(descriptors); bool cancel = false;
m_serializedDescriptors.swap(serializedDescriptors); const bool doFlush = m_descriptorsNumberInFile > descriptors.size();
if (doFlush && !m_serializedBlocks.empty())
if (m_descTreeDialog != nullptr)
{ {
#if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0 auto button = QMessageBox::question(this, "Information",
static_cast<EasyDescWidget*>(m_descTreeWidget->widget())->build(); QString("New blocks description number = %1\nis less than the old one = %2.\nTo avoid possible conflicts\nall profiled data will be deleted.\nContinue?")
#endif .arg(descriptors.size())
m_dialogDescTree->build(); .arg(m_descriptorsNumberInFile),
m_descTreeDialog->raise(); QMessageBox::Yes, QMessageBox::No);
if (button == QMessageBox::Yes)
clear(); // Clear all contents because new descriptors list conflicts with old one
else
cancel = true;
} }
else
if (!cancel)
{ {
onEditBlocksClicked(true); if (!doFlush && m_descriptorsNumberInFile < EASY_GLOBALS.descriptors.size())
{
// There are dynamically added descriptors, add them to the new list too
auto newnumber = static_cast<decltype(m_descriptorsNumberInFile)>(descriptors.size());
auto size = static_cast<decltype(m_descriptorsNumberInFile)>(EASY_GLOBALS.descriptors.size());
auto diff = newnumber - size;
decltype(newnumber) failnumber = 0;
descriptors.reserve(descriptors.size() + EASY_GLOBALS.descriptors.size() - m_descriptorsNumberInFile);
for (auto i = m_descriptorsNumberInFile; i < size; ++i)
{
auto id = EASY_GLOBALS.descriptors[i]->id();
if (id < newnumber)
descriptors.push_back(descriptors[id]);
else
++failnumber;
}
if (failnumber != 0)
{
// There are some errors...
// revert changes
descriptors.resize(newnumber);
// clear all profiled data to avoid conflicts
auto button = QMessageBox::question(this, "Information",
"There are errors while merging block descriptions lists.\nTo avoid possible conflicts\nall profiled data will be deleted.\nContinue?",
QMessageBox::Yes, QMessageBox::No);
if (button == QMessageBox::Yes)
clear(); // Clear all contents because new descriptors list conflicts with old one
else
cancel = true;
}
if (!cancel && diff != 0)
{
for (auto& b : EASY_GLOBALS.gui_blocks)
{
if (b.tree.node->id() >= m_descriptorsNumberInFile)
b.tree.node->setId(b.tree.node->id() + diff);
}
m_descriptorsNumberInFile = newnumber;
}
}
if (!cancel)
{
EASY_GLOBALS.descriptors.swap(descriptors);
m_serializedDescriptors.swap(serializedDescriptors);
if (m_descTreeDialog != nullptr)
{
#if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
static_cast<EasyDescWidget*>(m_descTreeWidget->widget())->build();
#endif
m_dialogDescTree->build();
m_descTreeDialog->raise();
}
else
{
onEditBlocksClicked(true);
}
}
} }
} }
else else

View File

@ -69,6 +69,7 @@ class EasyFileReader Q_DECL_FINAL
::std::stringstream m_stream; ///< ::std::stringstream m_stream; ///<
::std::stringstream m_errorMessage; ///< ::std::stringstream m_errorMessage; ///<
QString m_filename; ///< QString m_filename; ///<
uint32_t m_descriptorsNumberInFile = 0; ///<
::std::thread m_thread; ///< ::std::thread m_thread; ///<
::std::atomic_bool m_bDone; ///< ::std::atomic_bool m_bDone; ///<
::std::atomic<int> m_progress; ///< ::std::atomic<int> m_progress; ///<
@ -91,7 +92,7 @@ public:
void interrupt(); void interrupt();
void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors, void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree, ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
QString& _filename); uint32_t& _descriptorsNumberInFile, QString& _filename);
QString getError(); QString getError();
@ -180,12 +181,17 @@ protected:
class QLineEdit* m_ipEdit = nullptr; class QLineEdit* m_ipEdit = nullptr;
class QLineEdit* m_portEdit = nullptr; class QLineEdit* m_portEdit = nullptr;
class QAction* m_saveAction = nullptr;
class QAction* m_deleteAction = nullptr;
class QAction* m_captureAction = nullptr; class QAction* m_captureAction = nullptr;
class QAction* m_connectAction = nullptr; class QAction* m_connectAction = nullptr;
class QAction* m_eventTracingEnableAction = nullptr; class QAction* m_eventTracingEnableAction = nullptr;
class QAction* m_eventTracingPriorityAction = nullptr; class QAction* m_eventTracingPriorityAction = nullptr;
uint32_t m_descriptorsNumberInFile = 0;
uint16_t m_lastPort = 0; uint16_t m_lastPort = 0;
bool m_bNetworkFileRegime = false;
public: public:
@ -200,6 +206,7 @@ protected slots:
void onOpenFileClicked(bool); void onOpenFileClicked(bool);
void onReloadFileClicked(bool); void onReloadFileClicked(bool);
void onSaveFileClicked(bool);
void onDeleteClicked(bool); void onDeleteClicked(bool);
void onExitClicked(bool); void onExitClicked(bool);
void onEncodingChanged(bool); void onEncodingChanged(bool);
@ -207,6 +214,7 @@ protected slots:
void onEventIndicatorsChange(bool); void onEventIndicatorsChange(bool);
void onEnableDisableStatistics(bool); void onEnableDisableStatistics(bool);
void onDrawBordersChanged(bool); void onDrawBordersChanged(bool);
void onHideNarrowChildrenChanged(bool);
void onCollapseItemsAfterCloseChanged(bool); void onCollapseItemsAfterCloseChanged(bool);
void onAllItemsExpandedByDefaultChange(bool); void onAllItemsExpandedByDefaultChange(bool);
void onBindExpandStatusChange(bool); void onBindExpandStatusChange(bool);
@ -230,6 +238,8 @@ private:
// Private non-virtual methods // Private non-virtual methods
void clear();
void loadFile(const QString& filename); void loadFile(const QString& filename);
void readStream(::std::stringstream& data); void readStream(::std::stringstream& data);

View File

@ -2,7 +2,8 @@
<qresource> <qresource>
<file alias="logo">icons/logo.svg</file> <file alias="logo">icons/logo.svg</file>
<file alias="Exit">icons/off.svg</file> <file alias="Exit">icons/off.svg</file>
<file alias="Open">icons/open-folder.svg</file> <file alias="Open">icons/open-folder2.svg</file>
<file alias="Reopen">icons/reload-folder2.svg</file>
<file alias="Reload">icons/reload.svg</file> <file alias="Reload">icons/reload.svg</file>
<file alias="Expand">icons/expand.svg</file> <file alias="Expand">icons/expand.svg</file>
<file alias="Collapse">icons/collapse.svg</file> <file alias="Collapse">icons/collapse.svg</file>
@ -22,5 +23,6 @@
<file alias="List">icons/list.svg</file> <file alias="List">icons/list.svg</file>
<file alias="Search-next">icons/search-next.svg</file> <file alias="Search-next">icons/search-next.svg</file>
<file alias="Search-prev">icons/search-prev.svg</file> <file alias="Search-prev">icons/search-prev.svg</file>
<file alias="Settings">icons/settings.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -168,6 +168,7 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
} }
//const QSignalBlocker b(this); //const QSignalBlocker b(this);
const auto u_thread = ::profiler_gui::toUnicode("thread");
int i = 0; int i = 0;
const int total = static_cast<int>(_blocksTree.size()); const int total = static_cast<int>(_blocksTree.size());
for (const auto& threadTree : _blocksTree) for (const auto& threadTree : _blocksTree)
@ -178,10 +179,21 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
const auto& root = threadTree.second; const auto& root = threadTree.second;
auto item = new EasyTreeWidgetItem(); auto item = new EasyTreeWidgetItem();
if (root.got_name()) QString threadName;
item->setText(COL_NAME, QString("%1 Thread %2").arg(root.name()).arg(root.thread_id)); if (root.got_name())
else {
item->setText(COL_NAME, QString("Thread %1").arg(root.thread_id)); QString rootname(::profiler_gui::toUnicode(root.name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
threadName = ::std::move(QString("%1 %2").arg(rootname).arg(root.thread_id));
else
threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(root.thread_id));
}
else
{
threadName = ::std::move(QString("Thread %1").arg(root.thread_id));
}
item->setText(COL_NAME, threadName);
::profiler::timestamp_t duration = 0; ::profiler::timestamp_t duration = 0;
if (!root.children.empty()) if (!root.children.empty())
@ -239,6 +251,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
RootsMap threadsMap; RootsMap threadsMap;
const auto u_thread = ::profiler_gui::toUnicode("thread");
int i = 0, total = static_cast<int>(_blocks.size()); int i = 0, total = static_cast<int>(_blocks.size());
//const QSignalBlocker b(this); //const QSignalBlocker b(this);
for (const auto& block : _blocks) for (const auto& block : _blocks)
@ -266,10 +279,21 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
{ {
thread_item = new EasyTreeWidgetItem(); thread_item = new EasyTreeWidgetItem();
if (block.root->got_name()) QString threadName;
thread_item->setText(COL_NAME, QString("%1 Thread %2").arg(block.root->name()).arg(block.root->thread_id)); if (block.root->got_name())
else {
thread_item->setText(COL_NAME, QString("Thread %1").arg(block.root->thread_id)); QString rootname(::profiler_gui::toUnicode(block.root->name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
threadName = ::std::move(QString("%1 %2").arg(rootname).arg(block.root->thread_id));
else
threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(block.root->thread_id));
}
else
{
threadName = ::std::move(QString("Thread %1").arg(block.root->thread_id));
}
thread_item->setText(COL_NAME, threadName);
if (!block.root->children.empty()) if (!block.root->children.empty())
duration = blocksTree(block.root->children.back()).node->end() - blocksTree(block.root->children.front()).node->begin(); duration = blocksTree(block.root->children.back()).node->end() - blocksTree(block.root->children.front()).node->begin();

View File

@ -114,7 +114,9 @@ int main(int argc, char* argv[])
::profiler::descriptors_list_t descriptors; ::profiler::descriptors_list_t descriptors;
::profiler::blocks_t blocks; ::profiler::blocks_t blocks;
::std::stringstream errorMessage; ::std::stringstream errorMessage;
auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, blocks, threaded_trees, true, errorMessage); uint32_t descriptorsNumberInFile = 0;
auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, blocks,
threaded_trees, descriptorsNumberInFile, true, errorMessage);
if (blocks_counter == 0) if (blocks_counter == 0)
std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str(); std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str();

View File

@ -22,4 +22,4 @@ endif(UNIX)
target_link_libraries(${PROJECT_NAME} easy_profiler ${SPEC_LIB}) target_link_libraries(${PROJECT_NAME} easy_profiler ${SPEC_LIB})
target_link_libraries(${DISABLED_PROFILER_NAME} easy_profiler ${SPEC_LIB}) target_link_libraries(${DISABLED_PROFILER_NAME} easy_profiler ${SPEC_LIB})
target_compile_definitions(${DISABLED_PROFILER_NAME} PRIVATE FULL_DISABLE_PROFILER) target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_WITH_EASY_PROFILER)

View File

@ -25,6 +25,7 @@ set(SOURCES
) )
add_definitions( add_definitions(
-D_BUILD_PROFILER -D_BUILD_PROFILER
-DBUILD_WITH_EASY_PROFILER
) )
if(WIN32) if(WIN32)

View File

@ -117,7 +117,6 @@ extern "C" {
PROFILER_API void setLowPriorityEventTracing(bool) { } PROFILER_API void setLowPriorityEventTracing(bool) { }
#endif #endif
#ifndef _WIN32
PROFILER_API void setContextSwitchLogFilename(const char* name) PROFILER_API void setContextSwitchLogFilename(const char* name)
{ {
return MANAGER.setContextSwitchLogFilename(name); return MANAGER.setContextSwitchLogFilename(name);
@ -127,7 +126,6 @@ extern "C" {
{ {
return MANAGER.getContextSwitchLogFilename(); return MANAGER.getContextSwitchLogFilename();
} }
#endif
PROFILER_API void startListenSignalToCapture() PROFILER_API void startListenSignalToCapture()
{ {
@ -474,6 +472,9 @@ void ProfileManager::endBlock()
if (!m_isEnabled.load(std::memory_order_acquire)) if (!m_isEnabled.load(std::memory_order_acquire))
return; return;
if (THREAD_STORAGE == nullptr)
THREAD_STORAGE = &threadStorage(getCurrentThreadId());
if (THREAD_STORAGE->blocks.openedList.empty()) if (THREAD_STORAGE->blocks.openedList.empty())
return; return;

View File

@ -345,9 +345,7 @@ class ProfileManager
std::atomic_bool m_isEnabled; std::atomic_bool m_isEnabled;
std::atomic_bool m_isEventTracingEnabled; std::atomic_bool m_isEventTracingEnabled;
#ifndef _WIN32
std::string m_csInfoFilename = "/tmp/cs_profiling_info.log"; std::string m_csInfoFilename = "/tmp/cs_profiling_info.log";
#endif
uint32_t dumpBlocksToStream(profiler::OStream& _outputStream); uint32_t dumpBlocksToStream(profiler::OStream& _outputStream);
void setBlockStatus(profiler::block_id_t _id, profiler::EasyBlockStatus _status); void setBlockStatus(profiler::block_id_t _id, profiler::EasyBlockStatus _status);
@ -381,7 +379,6 @@ public:
uint32_t dumpBlocksToFile(const char* filename); uint32_t dumpBlocksToFile(const char* filename);
const char* registerThread(const char* name, profiler::ThreadGuard& threadGuard); const char* registerThread(const char* name, profiler::ThreadGuard& threadGuard);
#ifndef _WIN32
void setContextSwitchLogFilename(const char* name) void setContextSwitchLogFilename(const char* name)
{ {
m_csInfoFilename = name; m_csInfoFilename = name;
@ -391,7 +388,6 @@ public:
{ {
return m_csInfoFilename.c_str(); return m_csInfoFilename.c_str();
} }
#endif
void beginContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, const char* _target_process, bool _lockSpin = true); void beginContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, const char* _target_process, bool _lockSpin = true);
void storeContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, bool _lockSpin = true); void storeContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, bool _lockSpin = true);

View File

@ -60,6 +60,13 @@ const uint32_t COMPATIBLE_VERSIONS[] = {
}; };
const uint16_t COMPATIBLE_VERSIONS_NUM = sizeof(COMPATIBLE_VERSIONS) / sizeof(uint32_t); const uint16_t COMPATIBLE_VERSIONS_NUM = sizeof(COMPATIBLE_VERSIONS) / sizeof(uint32_t);
#undef EASY_FULL_VER
const int64_t TIME_FACTOR = 1000000000LL;
const uint32_t PROFILER_SIGNATURE = ('E' << 24) | ('a' << 16) | ('s' << 8) | 'y';
//////////////////////////////////////////////////////////////////////////
bool isCompatibleVersion(uint32_t _version) bool isCompatibleVersion(uint32_t _version)
{ {
if (_version == ::profiler::EASY_FULL_VERSION) if (_version == ::profiler::EASY_FULL_VERSION)
@ -67,18 +74,29 @@ bool isCompatibleVersion(uint32_t _version)
return COMPATIBLE_VERSIONS_NUM > 1 && ::std::binary_search(COMPATIBLE_VERSIONS + 1, COMPATIBLE_VERSIONS + COMPATIBLE_VERSIONS_NUM, _version); return COMPATIBLE_VERSIONS_NUM > 1 && ::std::binary_search(COMPATIBLE_VERSIONS + 1, COMPATIBLE_VERSIONS + COMPATIBLE_VERSIONS_NUM, _version);
} }
#undef EASY_FULL_VER inline void write(::std::stringstream& _stream, const char* _value, size_t _size)
{
_stream.write(_value, _size);
}
template <class T>
inline void write(::std::stringstream& _stream, const T& _value)
{
_stream.write((const char*)&_value, sizeof(T));
}
//////////////////////////////////////////////////////////////////////////
namespace profiler { namespace profiler {
void SerializedData::set(char* _data, size_t _size) void SerializedData::set(char* _data, uint64_t _size)
{ {
delete [] m_data; delete [] m_data;
m_data = _data; m_data = _data;
m_size = _size; m_size = _size;
} }
void SerializedData::set(size_t _size) void SerializedData::set(uint64_t _size)
{ {
if (_size != 0) if (_size != 0)
set(new char[_size], _size); set(new char[_size], _size);
@ -86,7 +104,7 @@ namespace profiler {
set(nullptr, 0); set(nullptr, 0);
} }
void SerializedData::extend(size_t _size) void SerializedData::extend(uint64_t _size)
{ {
auto olddata = m_data; auto olddata = m_data;
auto oldsize = m_size; auto oldsize = m_size;
@ -234,23 +252,24 @@ void validate_pointers(::std::atomic<int>& _progress, const char* _oldbase, ::pr
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
const int64_t TIME_FACTOR = 1000000000LL;
const uint32_t PROFILER_SIGNATURE = ('E' << 24) | ('a' << 16) | ('s' << 8) | 'y';
//////////////////////////////////////////////////////////////////////////
extern "C" { extern "C" {
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename, PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& blocks, ::profiler::blocks_t& blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics, uint32_t& total_descriptors_number,
::std::stringstream& _log) bool gather_statistics,
::std::stringstream& _log)
{ {
progress.store(0); auto oldprogress = progress.exchange(0, ::std::memory_order_release);
if (oldprogress < 0)
{
_log << "Reading was interrupted";
return 0;
}
::std::ifstream inFile(filename, ::std::fstream::binary); ::std::ifstream inFile(filename, ::std::fstream::binary);
if (!inFile.is_open()) if (!inFile.is_open())
@ -265,7 +284,8 @@ extern "C" {
stringstream_parent& s = str; stringstream_parent& s = str;
auto oldbuf = s.rdbuf(inFile.rdbuf()); auto oldbuf = s.rdbuf(inFile.rdbuf());
auto result = fillTreesFromStream(progress, str, serialized_blocks, serialized_descriptors, descriptors, blocks, threaded_trees, gather_statistics, _log); auto result = fillTreesFromStream(progress, str, serialized_blocks, serialized_descriptors, descriptors, blocks,
threaded_trees, total_descriptors_number, gather_statistics, _log);
s.rdbuf(oldbuf); s.rdbuf(oldbuf);
return result; return result;
@ -274,17 +294,23 @@ extern "C" {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& inFile, PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& inFile,
::profiler::SerializedData& serialized_blocks, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& blocks, ::profiler::blocks_t& blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
bool gather_statistics, uint32_t& total_descriptors_number,
::std::stringstream& _log) bool gather_statistics,
::std::stringstream& _log)
{ {
EASY_FUNCTION(::profiler::colors::Cyan); EASY_FUNCTION(::profiler::colors::Cyan);
progress.store(0); auto oldprogress = progress.exchange(0, ::std::memory_order_release);
if (oldprogress < 0)
{
_log << "Reading was interrupted";
return 0;
}
uint32_t signature = 0; uint32_t signature = 0;
inFile.read((char*)&signature, sizeof(uint32_t)); inFile.read((char*)&signature, sizeof(uint32_t));
@ -305,7 +331,8 @@ extern "C" {
int64_t cpu_frequency = 0LL; int64_t cpu_frequency = 0LL;
inFile.read((char*)&cpu_frequency, sizeof(int64_t)); inFile.read((char*)&cpu_frequency, sizeof(int64_t));
::profiler::timestamp_t begin_time = 0, end_time = 0; ::profiler::timestamp_t begin_time = 0ULL;
::profiler::timestamp_t end_time = 0ULL;
inFile.read((char*)&begin_time, sizeof(::profiler::timestamp_t)); inFile.read((char*)&begin_time, sizeof(::profiler::timestamp_t));
inFile.read((char*)&end_time, sizeof(::profiler::timestamp_t)); inFile.read((char*)&end_time, sizeof(::profiler::timestamp_t));
if (cpu_frequency != 0) if (cpu_frequency != 0)
@ -317,7 +344,7 @@ extern "C" {
} }
uint32_t total_blocks_number = 0; uint32_t total_blocks_number = 0;
inFile.read((char*)&total_blocks_number, sizeof(decltype(total_blocks_number))); inFile.read((char*)&total_blocks_number, sizeof(uint32_t));
if (total_blocks_number == 0) if (total_blocks_number == 0)
{ {
_log << "Profiled blocks number == 0"; _log << "Profiled blocks number == 0";
@ -332,8 +359,8 @@ extern "C" {
return 0; return 0;
} }
uint32_t total_descriptors_number = 0; total_descriptors_number = 0;
inFile.read((char*)&total_descriptors_number, sizeof(decltype(total_descriptors_number))); inFile.read((char*)&total_descriptors_number, sizeof(uint32_t));
if (total_descriptors_number == 0) if (total_descriptors_number == 0)
{ {
_log << "Blocks description number == 0"; _log << "Blocks description number == 0";