diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8615acd --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md index 634e463..d9b4b86 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ void bar() { ``` ## Collect blocks -There are two ways to cature blocks +There are two ways to capture blocks ### Collect via network diff --git a/easy_profiler_core/block.cpp b/easy_profiler_core/block.cpp index de0b7b7..ffc518d 100644 --- a/easy_profiler_core/block.cpp +++ b/easy_profiler_core/block.cpp @@ -52,7 +52,7 @@ #include "profile_manager.h" #include "current_time.h" -using namespace profiler; +namespace profiler { #ifndef EASY_PROFILER_API_DISABLED 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 - : CSwitchEvent(_begin_time, _tid) +} // END of namespace profiler. + +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) { diff --git a/easy_profiler_core/easy_socket.cpp b/easy_profiler_core/easy_socket.cpp index 05f6308..ab2f5eb 100644 --- a/easy_profiler_core/easy_socket.cpp +++ b/easy_profiler_core/easy_socket.cpp @@ -106,13 +106,12 @@ int EasySocket::bind(uint16_t port) if (!checkSocket(m_socket)) return -1; - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(port); - auto res = ::bind(m_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); - + struct sockaddr_in server_address; + memset(&server_address, 0, sizeof(server_address)); + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = INADDR_ANY; + server_address.sin_port = htons(port); + auto res = ::bind(m_socket, (struct sockaddr *)&server_address, sizeof(server_address)); return res; } diff --git a/easy_profiler_core/event_trace_win.cpp b/easy_profiler_core/event_trace_win.cpp index 871a797..78cf0ac 100644 --- a/easy_profiler_core/event_trace_win.cpp +++ b/easy_profiler_core/event_trace_win.cpp @@ -135,6 +135,34 @@ char KERNEL_LOGGER[] = KERNEL_LOGGER_NAME; ::std::atomic_uint64_t TRACING_END_TIME = ATOMIC_VAR_INIT(~0ULL); #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(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 { 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); if (hProc != nullptr) { - static TCHAR buf[MAX_PATH] = {}; // Using static is safe because processTraceEvent() is called from one thread - auto len = GetModuleBaseName(hProc, 0, buf, MAX_PATH); + std::size_t len = 0; + auto processName = getProcessName(hProc, len); // Using thread-unsafe method is safe because processTraceEvent() is called from one thread if (len != 0) { pinfo->name.reserve(pinfo->name.size() + 2 + len); pinfo->name.append(" ", 1); - pinfo->name.append(buf, len); + pinfo->name.append(processName, len); pinfo->valid = 1; } @@ -289,6 +317,17 @@ namespace profiler { MANAGER.endContextSwitch(_contextSwitchEvent->NewThreadId, pid, time); } + ////////////////////////////////////////////////////////////////////////// + + 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 @@ -328,7 +367,7 @@ namespace profiler { m_lowPriority.store(_value, ::std::memory_order_release); } - bool setPrivilege(HANDLE hToken, LPCSTR _privelegeName) + bool setPrivilege(HANDLE hToken, PTCHAR _privelegeName) { bool success = false; @@ -409,7 +448,7 @@ namespace profiler { */ // 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 // Stop another session diff --git a/easy_profiler_core/event_trace_win.h b/easy_profiler_core/event_trace_win.h index cb3c01b..1692891 100644 --- a/easy_profiler_core/event_trace_win.h +++ b/easy_profiler_core/event_trace_win.h @@ -81,6 +81,8 @@ namespace profiler { #pragma pack(push, 1) struct Properties { + Properties(); + EVENT_TRACE_PROPERTIES base; char sessionName[sizeof(KERNEL_LOGGER_NAME)]; }; diff --git a/easy_profiler_core/profile_manager.cpp b/easy_profiler_core/profile_manager.cpp index b09ecb6..5a364f9 100644 --- a/easy_profiler_core/profile_manager.cpp +++ b/easy_profiler_core/profile_manager.cpp @@ -775,6 +775,7 @@ const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _d } #else auto desc = new BlockDescriptor(static_cast(m_descriptors.size()), _defaultStatus, _name, _filename, _line, _block_type, _color); + (void)_copyName; // unused #endif m_descriptors.emplace_back(desc); diff --git a/easy_profiler_core/reader.cpp b/easy_profiler_core/reader.cpp index 4676374..7dc3e06 100644 --- a/easy_profiler_core/reader.cpp +++ b/easy_profiler_core/reader.cpp @@ -218,7 +218,7 @@ using CsStatsMap = ::std::unordered_map<::profiler::hashed_stdstring, ::profiler 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(); //StatsMap::key_type key(_current.node->name()); @@ -273,7 +273,7 @@ automatically receive statistics update. 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(); 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); for (auto i : _current.children) @@ -375,6 +375,20 @@ void validate_pointers(::std::atomic& _progress, const char* _oldbase, ::pr ////////////////////////////////////////////////////////////////////////// +static bool update_progress(::std::atomic& 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" { PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic& progress, const char* filename, @@ -388,10 +402,8 @@ extern "C" { bool gather_statistics, ::std::stringstream& _log) { - auto oldprogress = progress.exchange(0, ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, 0, _log)) { - _log << "Reading was interrupted"; return 0; } @@ -434,10 +446,8 @@ extern "C" { { EASY_FUNCTION(::profiler::colors::Cyan); - auto oldprogress = progress.exchange(0, ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, 0, _log)) { - _log << "Reading was interrupted"; return 0; } @@ -546,11 +556,9 @@ extern "C" { descriptors.push_back(descriptor); i += sz; - oldprogress = progress.exchange(static_cast(15 * i / descriptors_memory_size), ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, static_cast(15 * i / descriptors_memory_size), _log)) { - _log << "Reading was interrupted"; - return 0; // Loading interrupted + return 0; } } @@ -642,10 +650,8 @@ extern "C" { } } - oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, 20 + static_cast(70 * i / memory_size), _log)) { - _log << "Reading was 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 // TODO: check this behavior on Linux - for (auto i : tree.children) + for (auto child_block_index : tree.children) { - auto& child = blocks[i]; - child.per_parent_stats = update_statistics(per_parent_statistics, child, i, block_index, blocks); + auto& child = blocks[child_block_index]; + child.per_parent_stats = update_statistics(per_parent_statistics, child, child_block_index, block_index, blocks); if (tree.depth < child.depth) tree.depth = child.depth; } } 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) tree.depth = child.depth; } @@ -808,19 +814,15 @@ extern "C" { } } - oldprogress = progress.exchange(20 + static_cast(70 * i / memory_size), ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, 20 + static_cast(70 * i / memory_size), _log)) { - _log << "Reading was interrupted"; return 0; // Loading interrupted } } } - oldprogress = progress.exchange(90, ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, 90, _log)) { - _log << "Reading was interrupted"; return 0; // Loading interrupted } @@ -907,9 +909,9 @@ extern "C" { //}); //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) ++root.frames_number; @@ -1001,10 +1003,8 @@ extern "C" { descriptors.push_back(descriptor); i += sz; - auto oldprogress = progress.exchange(static_cast(100 * i / descriptors_memory_size), ::std::memory_order_release); - if (oldprogress < 0) + if (!update_progress(progress, static_cast(100 * i / descriptors_memory_size), _log)) { - _log << "Reading was interrupted"; return false; // Loading interrupted } } diff --git a/profiler_gui/blocks_tree_widget.cpp b/profiler_gui/blocks_tree_widget.cpp index 45e7858..ef29d90 100644 --- a/profiler_gui/blocks_tree_widget.cpp +++ b/profiler_gui/blocks_tree_widget.cpp @@ -798,7 +798,7 @@ void EasyTreeWidget::onCollapseAllClicked(bool) void EasyTreeWidget::onExpandAllClicked(bool) { - const QSignalBlocker b(this); + const QSignalBlocker blocker(this); m_bSilentExpandCollapse = true; expandAll(); diff --git a/profiler_gui/easy_graphics_scrollbar.cpp b/profiler_gui/easy_graphics_scrollbar.cpp index c7dee10..207d826 100644 --- a/profiler_gui/easy_graphics_scrollbar.cpp +++ b/profiler_gui/easy_graphics_scrollbar.cpp @@ -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(scene()->parent())->bindMode()) { @@ -273,7 +273,7 @@ QRectF EasyHistogramItem::boundingRect() const 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)))) return; @@ -1393,7 +1393,7 @@ void EasyHistogramItem::updateImage(QRectF _boundingRect, HistRegime _regime, qr qreal _minimum, qreal _maximum, qreal _range, qreal _value, qreal _width, qreal _top_duration, qreal _bottom_duration, 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 screenWidth = _boundingRect.width() * _current_scale; diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index be8c970..4c54883 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -878,11 +878,11 @@ void EasyMainWindow::loadFile(const QString& filename) m_reader.load(filename); } -void EasyMainWindow::readStream(::std::stringstream& data) +void EasyMainWindow::readStream(::std::stringstream& _data) { createProgressDialog(tr("Reading from stream...")); m_readerTimer.start(LOADER_TIMER_INTERVAL); - m_reader.load(data); + m_reader.load(_data); } ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/tree_widget_item.cpp b/profiler_gui/tree_widget_item.cpp index 4fd2459..b6e737f 100644 --- a/profiler_gui/tree_widget_item.cpp +++ b/profiler_gui/tree_widget_item.cpp @@ -164,8 +164,6 @@ bool EasyTreeWidgetItem::operator < (const Parent& _other) const return data(col, Qt::UserRole).toULongLong() < _other.data(col, Qt::UserRole).toULongLong(); } } - - return false; } bool EasyTreeWidgetItem::hasToolTip(int _column) const