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

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

# Conflicts:
#	easy_profiler_core/block.cpp
#	easy_profiler_core/profile_manager.cpp
#	easy_profiler_core/reader.cpp
#	profiler_gui/common_types.h
#	profiler_gui/descriptors_tree_widget.cpp
This commit is contained in:
Victor Zarubkin 2018-01-04 17:59:21 +03:00
commit 2c008b77ed
12 changed files with 118 additions and 56 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Sergey Yagovtsev, Victor Zarubkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -135,7 +135,7 @@ void bar() {
``` ```
## Collect blocks ## Collect blocks
There are two ways to cature blocks There are two ways to capture blocks
### Collect via network ### Collect via network

View File

@ -52,7 +52,7 @@
#include "profile_manager.h" #include "profile_manager.h"
#include "current_time.h" #include "current_time.h"
using namespace profiler; namespace profiler {
#ifndef EASY_PROFILER_API_DISABLED #ifndef EASY_PROFILER_API_DISABLED
Event::Event(timestamp_t _begin_time) EASY_NOEXCEPT : m_begin(_begin_time), m_end(0) Event::Event(timestamp_t _begin_time) EASY_NOEXCEPT : m_begin(_begin_time), m_end(0)
@ -231,8 +231,10 @@ CSwitchEvent::CSwitchEvent(timestamp_t _begin_time, thread_id_t _tid) EASY_NOEXC
} }
CSwitchBlock::CSwitchBlock(timestamp_t _begin_time, thread_id_t _tid, const char* _runtimeName) EASY_NOEXCEPT } // END of namespace profiler.
: CSwitchEvent(_begin_time, _tid)
CSwitchBlock::CSwitchBlock(profiler::timestamp_t _begin_time, profiler::thread_id_t _tid, const char* _runtimeName) EASY_NOEXCEPT
: profiler::CSwitchEvent(_begin_time, _tid)
, m_name(_runtimeName) , m_name(_runtimeName)
{ {

View File

@ -106,13 +106,12 @@ int EasySocket::bind(uint16_t port)
if (!checkSocket(m_socket)) if (!checkSocket(m_socket))
return -1; return -1;
struct sockaddr_in serv_addr; struct sockaddr_in server_address;
memset(&serv_addr, 0, sizeof(serv_addr)); memset(&server_address, 0, sizeof(server_address));
serv_addr.sin_family = AF_INET; server_address.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY; server_address.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port); server_address.sin_port = htons(port);
auto res = ::bind(m_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); auto res = ::bind(m_socket, (struct sockaddr *)&server_address, sizeof(server_address));
return res; return res;
} }

View File

@ -135,6 +135,34 @@ char KERNEL_LOGGER[] = KERNEL_LOGGER_NAME;
::std::atomic_uint64_t TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL); ::std::atomic_uint64_t TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL);
#endif #endif
/**
* Retrieve the process name of the given process.
*
* This method is NOT thread-safe: the returned string has to be copied somewhere before this
* method can be used by another thread or call.
*
* getProcessName() owns the returned string.
*
* \param len the process name string length [output].
*
* \return the process name string.
*/
static const char* getProcessName(HANDLE hProcess, std::size_t& len)
{
static TCHAR buf[MAX_PATH] = {};
len = static_cast<std::size_t>(GetModuleBaseName(hProcess, 0, buf, MAX_PATH));
if (len == 0)
return nullptr;
#if UNICODE
static char charbuf[MAX_PATH] = {};
len = std::wcstombs(charbuf, buf, len);
return charbuf;
#else
return buf;
#endif
}
namespace profiler { namespace profiler {
const decltype(EVENT_DESCRIPTOR::Opcode) SWITCH_CONTEXT_OPCODE = 36; const decltype(EVENT_DESCRIPTOR::Opcode) SWITCH_CONTEXT_OPCODE = 36;
@ -237,14 +265,14 @@ namespace profiler {
auto hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, pid); auto hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProc != nullptr) if (hProc != nullptr)
{ {
static TCHAR buf[MAX_PATH] = {}; // Using static is safe because processTraceEvent() is called from one thread std::size_t len = 0;
auto len = GetModuleBaseName(hProc, 0, buf, MAX_PATH); auto processName = getProcessName(hProc, len); // Using thread-unsafe method is safe because processTraceEvent() is called from one thread
if (len != 0) if (len != 0)
{ {
pinfo->name.reserve(pinfo->name.size() + 2 + len); pinfo->name.reserve(pinfo->name.size() + 2 + len);
pinfo->name.append(" ", 1); pinfo->name.append(" ", 1);
pinfo->name.append(buf, len); pinfo->name.append(processName, len);
pinfo->valid = 1; pinfo->valid = 1;
} }
@ -291,6 +319,17 @@ namespace profiler {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
EasyEventTracer::Properties::Properties()
{
#if UNICODE
std::wcstombs(sessionName, KERNEL_LOGGER_NAME, sizeof(sessionName));
#else
std::strncpy(sessionName, KERNEL_LOGGER_NAME, sizeof(sessionName));
#endif
}
//////////////////////////////////////////////////////////////////////////
#ifndef EASY_MAGIC_STATIC_AVAILABLE #ifndef EASY_MAGIC_STATIC_AVAILABLE
class EasyEventTracerInstance { class EasyEventTracerInstance {
friend EasyEventTracer; friend EasyEventTracer;
@ -328,7 +367,7 @@ namespace profiler {
m_lowPriority.store(_value, ::std::memory_order_release); m_lowPriority.store(_value, ::std::memory_order_release);
} }
bool setPrivilege(HANDLE hToken, LPCSTR _privelegeName) bool setPrivilege(HANDLE hToken, PTCHAR _privelegeName)
{ {
bool success = false; bool success = false;
@ -409,7 +448,7 @@ namespace profiler {
*/ */
// static is safe because we are guarded by spin-lock m_spin // static is safe because we are guarded by spin-lock m_spin
static Properties p = ([]{ Properties prp; strncpy(prp.sessionName, KERNEL_LOGGER_NAME, sizeof(prp.sessionName)); return prp; })(); static Properties p;
p.base = m_properties.base; // Use copy of m_properties to make sure m_properties will not be changed p.base = m_properties.base; // Use copy of m_properties to make sure m_properties will not be changed
// Stop another session // Stop another session

View File

@ -81,6 +81,8 @@ namespace profiler {
#pragma pack(push, 1) #pragma pack(push, 1)
struct Properties { struct Properties {
Properties();
EVENT_TRACE_PROPERTIES base; EVENT_TRACE_PROPERTIES base;
char sessionName[sizeof(KERNEL_LOGGER_NAME)]; char sessionName[sizeof(KERNEL_LOGGER_NAME)];
}; };

View File

@ -775,6 +775,7 @@ const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _d
} }
#else #else
auto desc = new BlockDescriptor(static_cast<block_id_t>(m_descriptors.size()), _defaultStatus, _name, _filename, _line, _block_type, _color); auto desc = new BlockDescriptor(static_cast<block_id_t>(m_descriptors.size()), _defaultStatus, _name, _filename, _line, _block_type, _color);
(void)_copyName; // unused
#endif #endif
m_descriptors.emplace_back(desc); m_descriptors.emplace_back(desc);

View File

@ -218,7 +218,7 @@ using CsStatsMap = ::std::unordered_map<::profiler::hashed_stdstring, ::profiler
automatically receive statistics update. automatically receive statistics update.
*/ */
::profiler::BlockStatistics* update_statistics(StatsMap& _stats_map, const ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, const ::profiler::blocks_t& _blocks, bool _calculate_children = true) static ::profiler::BlockStatistics* update_statistics(StatsMap& _stats_map, const ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, const ::profiler::blocks_t& _blocks, bool _calculate_children = true)
{ {
auto duration = _current.node->duration(); auto duration = _current.node->duration();
//StatsMap::key_type key(_current.node->name()); //StatsMap::key_type key(_current.node->name());
@ -273,7 +273,7 @@ automatically receive statistics update.
return stats; return stats;
} }
::profiler::BlockStatistics* update_statistics(CsStatsMap& _stats_map, const ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, const ::profiler::blocks_t& _blocks, bool _calculate_children = true) static ::profiler::BlockStatistics* update_statistics(CsStatsMap& _stats_map, const ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, const ::profiler::blocks_t& _blocks, bool _calculate_children = true)
{ {
auto duration = _current.node->duration(); auto duration = _current.node->duration();
CsStatsMap::key_type key(_current.node->name()); CsStatsMap::key_type key(_current.node->name());
@ -328,7 +328,7 @@ automatically receive statistics update.
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void update_statistics_recursive(StatsMap& _stats_map, ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, ::profiler::blocks_t& _blocks) static void update_statistics_recursive(StatsMap& _stats_map, ::profiler::BlocksTree& _current, ::profiler::block_index_t _current_index, ::profiler::block_index_t _parent_index, ::profiler::blocks_t& _blocks)
{ {
_current.per_frame_stats = update_statistics(_stats_map, _current, _current_index, _parent_index, _blocks, false); _current.per_frame_stats = update_statistics(_stats_map, _current, _current_index, _parent_index, _blocks, false);
for (auto i : _current.children) for (auto i : _current.children)
@ -375,6 +375,20 @@ void validate_pointers(::std::atomic<int>& _progress, const char* _oldbase, ::pr
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
static bool update_progress(::std::atomic<int>& progress, int new_value, ::std::stringstream& _log)
{
auto oldprogress = progress.exchange(new_value, ::std::memory_order_release);
if (oldprogress < 0)
{
_log << "Reading was interrupted";
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
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,
@ -388,10 +402,8 @@ extern "C" {
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log) ::std::stringstream& _log)
{ {
auto oldprogress = progress.exchange(0, ::std::memory_order_release); if (!update_progress(progress, 0, _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return 0; return 0;
} }
@ -434,10 +446,8 @@ extern "C" {
{ {
EASY_FUNCTION(::profiler::colors::Cyan); EASY_FUNCTION(::profiler::colors::Cyan);
auto oldprogress = progress.exchange(0, ::std::memory_order_release); if (!update_progress(progress, 0, _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return 0; return 0;
} }
@ -546,11 +556,9 @@ extern "C" {
descriptors.push_back(descriptor); descriptors.push_back(descriptor);
i += sz; i += sz;
oldprogress = progress.exchange(static_cast<int>(15 * i / descriptors_memory_size), ::std::memory_order_release); if (!update_progress(progress, static_cast<int>(15 * i / descriptors_memory_size), _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted"; return 0;
return 0; // Loading interrupted
} }
} }
@ -642,10 +650,8 @@ extern "C" {
} }
} }
oldprogress = progress.exchange(20 + static_cast<int>(70 * i / memory_size), ::std::memory_order_release); if (!update_progress(progress, 20 + static_cast<int>(70 * i / memory_size), _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return 0; // Loading interrupted return 0; // Loading interrupted
} }
} }
@ -760,19 +766,19 @@ extern "C" {
//per_parent_statistics.reserve(tree.children.size() * 2); // this gives no speed-up on Windows //per_parent_statistics.reserve(tree.children.size() * 2); // this gives no speed-up on Windows
// TODO: check this behavior on Linux // TODO: check this behavior on Linux
for (auto i : tree.children) for (auto child_block_index : tree.children)
{ {
auto& child = blocks[i]; auto& child = blocks[child_block_index];
child.per_parent_stats = update_statistics(per_parent_statistics, child, i, block_index, blocks); child.per_parent_stats = update_statistics(per_parent_statistics, child, child_block_index, block_index, blocks);
if (tree.depth < child.depth) if (tree.depth < child.depth)
tree.depth = child.depth; tree.depth = child.depth;
} }
} }
else else
{ {
for (auto i : tree.children) for (auto child_block_index : tree.children)
{ {
const auto& child = blocks[i]; const auto& child = blocks[child_block_index];
if (tree.depth < child.depth) if (tree.depth < child.depth)
tree.depth = child.depth; tree.depth = child.depth;
} }
@ -808,19 +814,15 @@ extern "C" {
} }
} }
oldprogress = progress.exchange(20 + static_cast<int>(70 * i / memory_size), ::std::memory_order_release); if (!update_progress(progress, 20 + static_cast<int>(70 * i / memory_size), _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return 0; // Loading interrupted return 0; // Loading interrupted
} }
} }
} }
oldprogress = progress.exchange(90, ::std::memory_order_release); if (!update_progress(progress, 90, _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return 0; // Loading interrupted return 0; // Loading interrupted
} }
@ -907,9 +909,9 @@ extern "C" {
//}); //});
//root.tree.shrink_to_fit(); //root.tree.shrink_to_fit();
for (auto i : root.children) for (auto child_block_index : root.children)
{ {
auto& frame = blocks[i]; auto& frame = blocks[child_block_index];
if (descriptors[frame.node->id()]->type() == ::profiler::BlockType::Block) if (descriptors[frame.node->id()]->type() == ::profiler::BlockType::Block)
++root.frames_number; ++root.frames_number;
@ -1001,10 +1003,8 @@ extern "C" {
descriptors.push_back(descriptor); descriptors.push_back(descriptor);
i += sz; i += sz;
auto oldprogress = progress.exchange(static_cast<int>(100 * i / descriptors_memory_size), ::std::memory_order_release); if (!update_progress(progress, static_cast<int>(100 * i / descriptors_memory_size), _log))
if (oldprogress < 0)
{ {
_log << "Reading was interrupted";
return false; // Loading interrupted return false; // Loading interrupted
} }
} }

View File

@ -798,7 +798,7 @@ void EasyTreeWidget::onCollapseAllClicked(bool)
void EasyTreeWidget::onExpandAllClicked(bool) void EasyTreeWidget::onExpandAllClicked(bool)
{ {
const QSignalBlocker b(this); const QSignalBlocker blocker(this);
m_bSilentExpandCollapse = true; m_bSilentExpandCollapse = true;
expandAll(); expandAll();

View File

@ -147,7 +147,7 @@ EasyGraphicsSliderItem::~EasyGraphicsSliderItem()
} }
void EasyGraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) void EasyGraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* /* _option */, QWidget* /* _widget */)
{ {
if (static_cast<const EasyGraphicsScrollbar*>(scene()->parent())->bindMode()) if (static_cast<const EasyGraphicsScrollbar*>(scene()->parent())->bindMode())
{ {
@ -273,7 +273,7 @@ QRectF EasyHistogramItem::boundingRect() const
return m_boundingRect; return m_boundingRect;
} }
void EasyHistogramItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget) void EasyHistogramItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* /* _option */, QWidget* /* _widget */)
{ {
if (!m_bPermitImageUpdate || (m_regime == Hist_Pointer && m_pSource == nullptr) || (m_regime == Hist_Id && (m_threadId == 0 || ::profiler_gui::is_max(m_blockId)))) if (!m_bPermitImageUpdate || (m_regime == Hist_Pointer && m_pSource == nullptr) || (m_regime == Hist_Id && (m_threadId == 0 || ::profiler_gui::is_max(m_blockId))))
return; return;
@ -1393,7 +1393,7 @@ void EasyHistogramItem::updateImage(QRectF _boundingRect, HistRegime _regime, qr
qreal _minimum, qreal _maximum, qreal _range, qreal _minimum, qreal _maximum, qreal _range,
qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration,
bool _bindMode, float _frame_time, ::profiler::timestamp_t _begin_time, bool _bindMode, float _frame_time, ::profiler::timestamp_t _begin_time,
qreal _origin, bool _autoAdjustHist) qreal /* _origin */, bool _autoAdjustHist)
{ {
const auto bottom = _boundingRect.height();//_boundingRect.bottom(); const auto bottom = _boundingRect.height();//_boundingRect.bottom();
const auto screenWidth = _boundingRect.width() * _current_scale; const auto screenWidth = _boundingRect.width() * _current_scale;

View File

@ -878,11 +878,11 @@ void EasyMainWindow::loadFile(const QString& filename)
m_reader.load(filename); m_reader.load(filename);
} }
void EasyMainWindow::readStream(::std::stringstream& data) void EasyMainWindow::readStream(::std::stringstream& _data)
{ {
createProgressDialog(tr("Reading from stream...")); createProgressDialog(tr("Reading from stream..."));
m_readerTimer.start(LOADER_TIMER_INTERVAL); m_readerTimer.start(LOADER_TIMER_INTERVAL);
m_reader.load(data); m_reader.load(_data);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -164,8 +164,6 @@ bool EasyTreeWidgetItem::operator < (const Parent& _other) const
return data(col, Qt::UserRole).toULongLong() < _other.data(col, Qt::UserRole).toULongLong(); return data(col, Qt::UserRole).toULongLong() < _other.data(col, Qt::UserRole).toULongLong();
} }
} }
return false;
} }
bool EasyTreeWidgetItem::hasToolTip(int _column) const bool EasyTreeWidgetItem::hasToolTip(int _column) const