mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 16:11:02 +08:00
Merge remote-tracking branch 'origin/saving_file_develop' into develop
This commit is contained in:
commit
ca80ca0ccb
@ -62,11 +62,12 @@ profiler::block_index_t FileReader::readFile(const std::string& filename)
|
||||
profiler::blocks_t blocks;
|
||||
profiler::thread_blocks_tree_t threaded_trees;
|
||||
|
||||
profiler::processid_t pid = 0;
|
||||
uint32_t total_descriptors_number = 0;
|
||||
|
||||
EASY_CONSTEXPR bool DoNotGatherStats = false;
|
||||
const auto blocks_number = ::fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors,
|
||||
descriptors, blocks, threaded_trees, total_descriptors_number, m_version, DoNotGatherStats, m_errorMessage);
|
||||
descriptors, blocks, threaded_trees, total_descriptors_number, m_version, pid, DoNotGatherStats, m_errorMessage);
|
||||
|
||||
if (blocks_number == 0)
|
||||
return 0;
|
||||
|
274
easy_profiler_core/alignment_helpers.h
Normal file
274
easy_profiler_core/alignment_helpers.h
Normal file
@ -0,0 +1,274 @@
|
||||
/************************************************
|
||||
* creation time : 2017/08/20
|
||||
* author : Blake Martin
|
||||
* email : rationalcoder@gmail.com
|
||||
************************************************/
|
||||
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||
|
||||
Licensed under either of
|
||||
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
at your option.
|
||||
|
||||
The MIT License
|
||||
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.
|
||||
|
||||
|
||||
The Apache License, Version 2.0 (the "License");
|
||||
You may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef EASY_PROFILER_ALIGNMENT_HELPERS_H
|
||||
#define EASY_PROFILER_ALIGNMENT_HELPERS_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
|
||||
//! Checks if a pointer is aligned.
|
||||
//! \param ptr The pointer to check.
|
||||
//! \param alignment The alignement (must be a power of 2)
|
||||
//! \returns true if the memory is aligned.
|
||||
//!
|
||||
template <uint32_t ALIGNMENT>
|
||||
EASY_FORCE_INLINE bool is_aligned(void* ptr)
|
||||
{
|
||||
static_assert((ALIGNMENT & 1) == 0, "Alignment must be a power of two.");
|
||||
return ((uintptr_t)ptr & (ALIGNMENT-1)) == 0;
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero16(void* ptr)
|
||||
{
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(uint16_t*)ptr = 0;
|
||||
#else
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero32(void* ptr)
|
||||
{
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(uint32_t*)ptr = 0;
|
||||
#else
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
((char*)ptr)[2] = 0;
|
||||
((char*)ptr)[3] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero64(void* ptr)
|
||||
{
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
// Assume unaligned is more common.
|
||||
if (!is_aligned<alignof(uint64_t)>(ptr)) {
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
((char*)ptr)[2] = 0;
|
||||
((char*)ptr)[3] = 0;
|
||||
((char*)ptr)[4] = 0;
|
||||
((char*)ptr)[5] = 0;
|
||||
((char*)ptr)[6] = 0;
|
||||
((char*)ptr)[7] = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*(uint64_t*)ptr = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store16(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(T*)ptr = val;
|
||||
#else
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store32(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(T*)ptr = val;
|
||||
#else
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
((char*)ptr)[2] = temp[2];
|
||||
((char*)ptr)[3] = temp[3];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store64(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
// Assume unaligned is more common.
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
((char*)ptr)[2] = temp[2];
|
||||
((char*)ptr)[3] = temp[3];
|
||||
((char*)ptr)[4] = temp[4];
|
||||
((char*)ptr)[5] = temp[5];
|
||||
((char*)ptr)[6] = temp[6];
|
||||
((char*)ptr)[7] = temp[7];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*(T*)ptr = val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load16(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
return *(const T*)ptr;
|
||||
#else
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load16(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*val = *(const T*)ptr;
|
||||
#else
|
||||
((char*)val)[0] = ((const char*)ptr)[0];
|
||||
((char*)val)[1] = ((const char*)ptr)[1];
|
||||
#endif
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load32(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
return *(const T*)ptr;
|
||||
#else
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
((char*)&value)[2] = ((const char*)ptr)[2];
|
||||
((char*)&value)[3] = ((const char*)ptr)[3];
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load32(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*val = *(const T*)ptr;
|
||||
#else
|
||||
((char*)&val)[0] = ((const char*)ptr)[0];
|
||||
((char*)&val)[1] = ((const char*)ptr)[1];
|
||||
((char*)&val)[2] = ((const char*)ptr)[2];
|
||||
((char*)&val)[3] = ((const char*)ptr)[3];
|
||||
#endif
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load64(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
((char*)&value)[2] = ((const char*)ptr)[2];
|
||||
((char*)&value)[3] = ((const char*)ptr)[3];
|
||||
((char*)&value)[4] = ((const char*)ptr)[4];
|
||||
((char*)&value)[5] = ((const char*)ptr)[5];
|
||||
((char*)&value)[6] = ((const char*)ptr)[6];
|
||||
((char*)&value)[7] = ((const char*)ptr)[7];
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(const T*)ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load64(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
((char*)&val)[0] = ((const char*)ptr)[0];
|
||||
((char*)&val)[1] = ((const char*)ptr)[1];
|
||||
((char*)&val)[2] = ((const char*)ptr)[2];
|
||||
((char*)&val)[3] = ((const char*)ptr)[3];
|
||||
((char*)&val)[4] = ((const char*)ptr)[4];
|
||||
((char*)&val)[5] = ((const char*)ptr)[5];
|
||||
((char*)&val)[6] = ((const char*)ptr)[6];
|
||||
((char*)&val)[7] = ((const char*)ptr)[7];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*val = *(const T*)ptr;
|
||||
return *val;
|
||||
}
|
||||
|
||||
#endif //EASY_PROFILER_ALIGNMENT_HELPERS_H
|
@ -45,9 +45,8 @@ The Apache License, Version 2.0 (the "License");
|
||||
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
#include <stdint.h>
|
||||
#include "outstream.h"
|
||||
#include "alignment_helpers.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -83,226 +82,6 @@ The Apache License, Version 2.0 (the "License");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Checks if a pointer is aligned.
|
||||
//! \param ptr The pointer to check.
|
||||
//! \param alignment The alignement (must be a power of 2)
|
||||
//! \returns true if the memory is aligned.
|
||||
//!
|
||||
template <uint32_t ALIGNMENT>
|
||||
EASY_FORCE_INLINE bool is_aligned(void* ptr)
|
||||
{
|
||||
static_assert((ALIGNMENT & 1) == 0, "Alignment must be a power of two.");
|
||||
return ((uintptr_t)ptr & (ALIGNMENT-1)) == 0;
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero16(void* ptr)
|
||||
{
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(uint16_t*)ptr = 0;
|
||||
#else
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero32(void* ptr)
|
||||
{
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(uint32_t*)ptr = 0;
|
||||
#else
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
((char*)ptr)[2] = 0;
|
||||
((char*)ptr)[3] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE void unaligned_zero64(void* ptr)
|
||||
{
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
// Assume unaligned is more common.
|
||||
if (!is_aligned<alignof(uint64_t)>(ptr)) {
|
||||
((char*)ptr)[0] = 0;
|
||||
((char*)ptr)[1] = 0;
|
||||
((char*)ptr)[2] = 0;
|
||||
((char*)ptr)[3] = 0;
|
||||
((char*)ptr)[4] = 0;
|
||||
((char*)ptr)[5] = 0;
|
||||
((char*)ptr)[6] = 0;
|
||||
((char*)ptr)[7] = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*(uint64_t*)ptr = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store16(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(T*)ptr = val;
|
||||
#else
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store32(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*(T*)ptr = val;
|
||||
#else
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
((char*)ptr)[2] = temp[2];
|
||||
((char*)ptr)[3] = temp[3];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE void unaligned_store64(void* ptr, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
// Assume unaligned is more common.
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
const char* const temp = (const char*)&val;
|
||||
((char*)ptr)[0] = temp[0];
|
||||
((char*)ptr)[1] = temp[1];
|
||||
((char*)ptr)[2] = temp[2];
|
||||
((char*)ptr)[3] = temp[3];
|
||||
((char*)ptr)[4] = temp[4];
|
||||
((char*)ptr)[5] = temp[5];
|
||||
((char*)ptr)[6] = temp[6];
|
||||
((char*)ptr)[7] = temp[7];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*(T*)ptr = val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load16(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
return *(const T*)ptr;
|
||||
#else
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load16(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 2, "16 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*val = *(const T*)ptr;
|
||||
#else
|
||||
((char*)val)[0] = ((const char*)ptr)[0];
|
||||
((char*)val)[1] = ((const char*)ptr)[1];
|
||||
#endif
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load32(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
return *(const T*)ptr;
|
||||
#else
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
((char*)&value)[2] = ((const char*)ptr)[2];
|
||||
((char*)&value)[3] = ((const char*)ptr)[3];
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load32(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "32 bit type required.");
|
||||
|
||||
#ifndef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
*val = *(const T*)ptr;
|
||||
#else
|
||||
((char*)&val)[0] = ((const char*)ptr)[0];
|
||||
((char*)&val)[1] = ((const char*)ptr)[1];
|
||||
((char*)&val)[2] = ((const char*)ptr)[2];
|
||||
((char*)&val)[3] = ((const char*)ptr)[3];
|
||||
#endif
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load64(const void* ptr)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
T value;
|
||||
((char*)&value)[0] = ((const char*)ptr)[0];
|
||||
((char*)&value)[1] = ((const char*)ptr)[1];
|
||||
((char*)&value)[2] = ((const char*)ptr)[2];
|
||||
((char*)&value)[3] = ((const char*)ptr)[3];
|
||||
((char*)&value)[4] = ((const char*)ptr)[4];
|
||||
((char*)&value)[5] = ((const char*)ptr)[5];
|
||||
((char*)&value)[6] = ((const char*)ptr)[6];
|
||||
((char*)&value)[7] = ((const char*)ptr)[7];
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(const T*)ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EASY_FORCE_INLINE T unaligned_load64(const void* ptr, T* val)
|
||||
{
|
||||
static_assert(sizeof(T) == 8, "64 bit type required.");
|
||||
|
||||
#ifdef EASY_ENABLE_STRICT_ALIGNMENT
|
||||
if (!is_aligned<alignof(T)>(ptr)) {
|
||||
((char*)&val)[0] = ((const char*)ptr)[0];
|
||||
((char*)&val)[1] = ((const char*)ptr)[1];
|
||||
((char*)&val)[2] = ((const char*)ptr)[2];
|
||||
((char*)&val)[3] = ((const char*)ptr)[3];
|
||||
((char*)&val)[4] = ((const char*)ptr)[4];
|
||||
((char*)&val)[5] = ((const char*)ptr)[5];
|
||||
((char*)&val)[6] = ((const char*)ptr)[6];
|
||||
((char*)&val)[7] = ((const char*)ptr)[7];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
*val = *(const T*)ptr;
|
||||
return *val;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <const uint16_t N>
|
||||
class chunk_allocator
|
||||
{
|
||||
|
@ -45,32 +45,36 @@ The Apache License, Version 2.0 (the "License");
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <easy/serialized_block.h>
|
||||
#include <easy/details/arbitrary_value_public_types.h>
|
||||
#include <easy/utility.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace profiler {
|
||||
|
||||
using processid_t = uint64_t;
|
||||
using calls_number_t = uint32_t;
|
||||
using block_index_t = uint32_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct BlockStatistics EASY_FINAL
|
||||
{
|
||||
::profiler::timestamp_t total_duration; ///< Total duration of all block calls
|
||||
::profiler::timestamp_t total_children_duration; ///< Total duration of all children of all block calls
|
||||
::profiler::block_index_t min_duration_block; ///< Will be used in GUI to jump to the block with min duration
|
||||
::profiler::block_index_t max_duration_block; ///< Will be used in GUI to jump to the block with max duration
|
||||
::profiler::block_index_t parent_block; ///< Index of block which is "parent" for "per_parent_stats" or "frame" for "per_frame_stats" or thread-id for "per_thread_stats"
|
||||
::profiler::calls_number_t calls_number; ///< Block calls number
|
||||
profiler::timestamp_t total_duration; ///< Total duration of all block calls
|
||||
profiler::timestamp_t total_children_duration; ///< Total duration of all children of all block calls
|
||||
profiler::block_index_t min_duration_block; ///< Will be used in GUI to jump to the block with min duration
|
||||
profiler::block_index_t max_duration_block; ///< Will be used in GUI to jump to the block with max duration
|
||||
profiler::block_index_t parent_block; ///< Index of block which is "parent" for "per_parent_stats" or "frame" for "per_frame_stats" or thread-id for "per_thread_stats"
|
||||
profiler::calls_number_t calls_number; ///< Block calls number
|
||||
|
||||
explicit BlockStatistics(::profiler::timestamp_t _duration, ::profiler::block_index_t _block_index, ::profiler::block_index_t _parent_index)
|
||||
explicit BlockStatistics(profiler::timestamp_t _duration, profiler::block_index_t _block_index, profiler::block_index_t _parent_index)
|
||||
: total_duration(_duration)
|
||||
, total_children_duration(0)
|
||||
, min_duration_block(_block_index)
|
||||
@ -82,7 +86,7 @@ namespace profiler {
|
||||
|
||||
//BlockStatistics() = default;
|
||||
|
||||
inline ::profiler::timestamp_t average_duration() const
|
||||
inline profiler::timestamp_t average_duration() const
|
||||
{
|
||||
return total_duration / calls_number;
|
||||
}
|
||||
@ -100,20 +104,20 @@ namespace profiler {
|
||||
|
||||
public:
|
||||
|
||||
using blocks_t = ::std::vector<This>;
|
||||
using children_t = ::std::vector<::profiler::block_index_t>;
|
||||
using blocks_t = std::vector<This>;
|
||||
using children_t = std::vector<profiler::block_index_t>;
|
||||
|
||||
children_t children; ///< List of children blocks. May be empty.
|
||||
|
||||
union {
|
||||
::profiler::SerializedBlock* node; ///< Pointer to serialized data for regular block (id, name, begin, end etc.)
|
||||
::profiler::SerializedCSwitch* cs; ///< Pointer to serialized data for context switch (thread_id, name, begin, end etc.)
|
||||
::profiler::ArbitraryValue* value; ///< Pointer to serialized data for arbitrary value
|
||||
profiler::SerializedBlock* node; ///< Pointer to serialized data for regular block (id, name, begin, end etc.)
|
||||
profiler::SerializedCSwitch* cs; ///< Pointer to serialized data for context switch (thread_id, name, begin, end etc.)
|
||||
profiler::ArbitraryValue* value; ///< Pointer to serialized data for arbitrary value
|
||||
};
|
||||
|
||||
::profiler::BlockStatistics* per_parent_stats; ///< Pointer to statistics for this block within the parent (may be nullptr for top-level blocks)
|
||||
::profiler::BlockStatistics* per_frame_stats; ///< Pointer to statistics for this block within the frame (may be nullptr for top-level blocks)
|
||||
::profiler::BlockStatistics* per_thread_stats; ///< Pointer to statistics for this block within the bounds of all frames per current thread
|
||||
profiler::BlockStatistics* per_parent_stats; ///< Pointer to statistics for this block within the parent (may be nullptr for top-level blocks)
|
||||
profiler::BlockStatistics* per_frame_stats; ///< Pointer to statistics for this block within the frame (may be nullptr for top-level blocks)
|
||||
profiler::BlockStatistics* per_thread_stats; ///< Pointer to statistics for this block within the bounds of all frames per current thread
|
||||
uint8_t depth; ///< Maximum number of sublevels (maximum children depth)
|
||||
|
||||
BlocksTree(const This&) = delete;
|
||||
@ -132,12 +136,12 @@ namespace profiler {
|
||||
BlocksTree(This&& that) EASY_NOEXCEPT
|
||||
: BlocksTree()
|
||||
{
|
||||
make_move(::std::forward<This&&>(that));
|
||||
make_move(std::forward<This&&>(that));
|
||||
}
|
||||
|
||||
This& operator = (This&& that) EASY_NOEXCEPT
|
||||
{
|
||||
make_move(::std::forward<This&&>(that));
|
||||
make_move(std::forward<This&&>(that));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -166,7 +170,7 @@ namespace profiler {
|
||||
// shrink version 2:
|
||||
//children_t new_children;
|
||||
//new_children.reserve(children.size());
|
||||
//::std::move(children.begin(), children.end(), ::std::back_inserter(new_children));
|
||||
//std::move(children.begin(), children.end(), std::back_inserter(new_children));
|
||||
//new_children.swap(children);
|
||||
}
|
||||
|
||||
@ -183,7 +187,7 @@ namespace profiler {
|
||||
if (per_frame_stats != that.per_frame_stats)
|
||||
release_stats(per_frame_stats);
|
||||
|
||||
children = ::std::move(that.children);
|
||||
children = std::move(that.children);
|
||||
node = that.node;
|
||||
per_parent_stats = that.per_parent_stats;
|
||||
per_frame_stats = that.per_frame_stats;
|
||||
@ -210,11 +214,11 @@ namespace profiler {
|
||||
BlocksTree::children_t sync; ///< List of context-switch events
|
||||
BlocksTree::children_t events; ///< List of events indexes
|
||||
std::string thread_name; ///< Name of this thread
|
||||
::profiler::timestamp_t profiled_time; ///< Profiled time of this thread (sum of all children duration)
|
||||
::profiler::timestamp_t wait_time; ///< Wait time of this thread (sum of all context switches)
|
||||
::profiler::thread_id_t thread_id; ///< System Id of this thread
|
||||
::profiler::block_index_t frames_number; ///< Total frames number (top-level blocks)
|
||||
::profiler::block_index_t blocks_number; ///< Total blocks number including their children
|
||||
profiler::timestamp_t profiled_time; ///< Profiled time of this thread (sum of all children duration)
|
||||
profiler::timestamp_t wait_time; ///< Wait time of this thread (sum of all context switches)
|
||||
profiler::thread_id_t thread_id; ///< System Id of this thread
|
||||
profiler::block_index_t frames_number; ///< Total frames number (top-level blocks)
|
||||
profiler::block_index_t blocks_number; ///< Total blocks number including their children
|
||||
uint8_t depth; ///< Maximum stack depth (number of levels)
|
||||
|
||||
BlocksTreeRoot(const This&) = delete;
|
||||
@ -226,10 +230,10 @@ namespace profiler {
|
||||
}
|
||||
|
||||
BlocksTreeRoot(This&& that) EASY_NOEXCEPT
|
||||
: children(::std::move(that.children))
|
||||
, sync(::std::move(that.sync))
|
||||
, events(::std::move(that.events))
|
||||
, thread_name(::std::move(that.thread_name))
|
||||
: children(std::move(that.children))
|
||||
, sync(std::move(that.sync))
|
||||
, events(std::move(that.events))
|
||||
, thread_name(std::move(that.thread_name))
|
||||
, profiled_time(that.profiled_time)
|
||||
, wait_time(that.wait_time)
|
||||
, thread_id(that.thread_id)
|
||||
@ -241,10 +245,10 @@ namespace profiler {
|
||||
|
||||
This& operator = (This&& that) EASY_NOEXCEPT
|
||||
{
|
||||
children = ::std::move(that.children);
|
||||
sync = ::std::move(that.sync);
|
||||
events = ::std::move(that.events);
|
||||
thread_name = ::std::move(that.thread_name);
|
||||
children = std::move(that.children);
|
||||
sync = std::move(that.sync);
|
||||
events = std::move(that.events);
|
||||
thread_name = std::move(that.thread_name);
|
||||
profiled_time = that.profiled_time;
|
||||
wait_time = that.wait_time;
|
||||
thread_id = that.thread_id;
|
||||
@ -271,93 +275,49 @@ namespace profiler {
|
||||
|
||||
}; // END of class BlocksTreeRoot.
|
||||
|
||||
using blocks_t = ::profiler::BlocksTree::blocks_t;
|
||||
using thread_blocks_tree_t = ::std::unordered_map<::profiler::thread_id_t, ::profiler::BlocksTreeRoot, ::estd::hash<::profiler::thread_id_t> >;
|
||||
using blocks_t = profiler::BlocksTree::blocks_t;
|
||||
using thread_blocks_tree_t = std::unordered_map<profiler::thread_id_t, profiler::BlocksTreeRoot, ::estd::hash<profiler::thread_id_t> >;
|
||||
using block_getter_fn = std::function<const profiler::BlocksTree&(profiler::block_index_t)>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PROFILER_API SerializedData EASY_FINAL
|
||||
{
|
||||
char* m_data;
|
||||
size_t m_size;
|
||||
uint64_t m_size;
|
||||
char* m_data;
|
||||
|
||||
public:
|
||||
|
||||
SerializedData(const SerializedData&) = delete;
|
||||
SerializedData& operator = (const SerializedData&) = delete;
|
||||
|
||||
SerializedData() : m_data(nullptr), m_size(0)
|
||||
{
|
||||
}
|
||||
SerializedData();
|
||||
|
||||
SerializedData(SerializedData&& that) : m_data(that.m_data), m_size(that.m_size)
|
||||
{
|
||||
that.m_data = nullptr;
|
||||
that.m_size = 0;
|
||||
}
|
||||
SerializedData(SerializedData&& that);
|
||||
|
||||
~SerializedData()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
~SerializedData();
|
||||
|
||||
void set(uint64_t _size);
|
||||
|
||||
void extend(uint64_t _size);
|
||||
|
||||
SerializedData& operator = (SerializedData&& that)
|
||||
{
|
||||
set(that.m_data, that.m_size);
|
||||
that.m_data = nullptr;
|
||||
that.m_size = 0;
|
||||
return *this;
|
||||
}
|
||||
SerializedData& operator = (SerializedData&& that);
|
||||
|
||||
char* operator [] (uint64_t i)
|
||||
{
|
||||
return m_data + i;
|
||||
}
|
||||
char* operator [] (uint64_t i);
|
||||
|
||||
const char* operator [] (uint64_t i) const
|
||||
{
|
||||
return m_data + i;
|
||||
}
|
||||
const char* operator [] (uint64_t i) const;
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
bool empty() const;
|
||||
|
||||
uint64_t size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
uint64_t size() const;
|
||||
|
||||
char* data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
char* data();
|
||||
|
||||
const char* data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
const char* data() const;
|
||||
|
||||
void clear()
|
||||
{
|
||||
set(nullptr, 0);
|
||||
}
|
||||
void clear();
|
||||
|
||||
void swap(SerializedData& other)
|
||||
{
|
||||
char* d = other.m_data;
|
||||
uint64_t sz = other.m_size;
|
||||
|
||||
other.m_data = m_data;
|
||||
other.m_size = m_size;
|
||||
|
||||
m_data = d;
|
||||
m_size = (size_t)sz;
|
||||
}
|
||||
void swap(SerializedData& other);
|
||||
|
||||
private:
|
||||
|
||||
@ -367,59 +327,117 @@ namespace profiler {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using descriptors_list_t = ::std::vector<SerializedBlockDescriptor*>;
|
||||
using descriptors_list_t = std::vector<SerializedBlockDescriptor*>;
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
extern "C" {
|
||||
|
||||
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
|
||||
::profiler::SerializedData& serialized_blocks,
|
||||
::profiler::SerializedData& serialized_descriptors,
|
||||
::profiler::descriptors_list_t& descriptors,
|
||||
::profiler::blocks_t& _blocks,
|
||||
::profiler::thread_blocks_tree_t& threaded_trees,
|
||||
PROFILER_API profiler::block_index_t fillTreesFromFile(std::atomic<int>& progress, const char* filename,
|
||||
profiler::SerializedData& serialized_blocks,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
profiler::blocks_t& _blocks,
|
||||
profiler::thread_blocks_tree_t& threaded_trees,
|
||||
uint32_t& total_descriptors_number,
|
||||
uint32_t& version,
|
||||
profiler::processid_t& pid,
|
||||
bool gather_statistics,
|
||||
std::ostream& _log);
|
||||
|
||||
PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<int>& progress, std::istream& str,
|
||||
profiler::SerializedData& serialized_blocks,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
profiler::blocks_t& _blocks,
|
||||
profiler::thread_blocks_tree_t& threaded_trees,
|
||||
uint32_t& total_descriptors_number,
|
||||
uint32_t& version,
|
||||
profiler::processid_t& pid,
|
||||
bool gather_statistics,
|
||||
::std::stringstream& _log);
|
||||
std::ostream& _log);
|
||||
|
||||
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
|
||||
::profiler::SerializedData& serialized_blocks,
|
||||
::profiler::SerializedData& serialized_descriptors,
|
||||
::profiler::descriptors_list_t& descriptors,
|
||||
::profiler::blocks_t& _blocks,
|
||||
::profiler::thread_blocks_tree_t& threaded_trees,
|
||||
uint32_t& total_descriptors_number,
|
||||
uint32_t& version,
|
||||
bool gather_statistics,
|
||||
::std::stringstream& _log);
|
||||
PROFILER_API bool readDescriptionsFromStream(std::atomic<int>& progress, std::istream& str,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
std::ostream& _log);
|
||||
|
||||
PROFILER_API bool readDescriptionsFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
|
||||
::profiler::SerializedData& serialized_descriptors,
|
||||
::profiler::descriptors_list_t& descriptors,
|
||||
::std::stringstream& _log);
|
||||
PROFILER_API profiler::block_index_t writeTreesToFile(std::atomic<int>& progress, const char* filename,
|
||||
const profiler::SerializedData& serialized_descriptors,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_t descriptors_count,
|
||||
const profiler::thread_blocks_tree_t& trees,
|
||||
profiler::block_getter_fn block_getter,
|
||||
profiler::timestamp_t begin_time,
|
||||
profiler::timestamp_t end_time,
|
||||
profiler::processid_t pid,
|
||||
std::ostream& log);
|
||||
|
||||
PROFILER_API profiler::block_index_t writeTreesToStream(std::atomic<int>& progress, std::ostream& str,
|
||||
const profiler::SerializedData& serialized_descriptors,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_t descriptors_count,
|
||||
const profiler::thread_blocks_tree_t& trees,
|
||||
profiler::block_getter_fn block_getter,
|
||||
profiler::timestamp_t begin_time,
|
||||
profiler::timestamp_t end_time,
|
||||
profiler::processid_t pid,
|
||||
std::ostream& log);
|
||||
}
|
||||
|
||||
inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks,
|
||||
::profiler::SerializedData& serialized_descriptors,
|
||||
::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks,
|
||||
::profiler::thread_blocks_tree_t& threaded_trees,
|
||||
uint32_t& total_descriptors_number,
|
||||
uint32_t& version,
|
||||
bool gather_statistics,
|
||||
::std::stringstream& _log)
|
||||
inline profiler::block_index_t fillTreesFromFile(const char* filename, profiler::SerializedData& serialized_blocks,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors, profiler::blocks_t& _blocks,
|
||||
profiler::thread_blocks_tree_t& threaded_trees,
|
||||
uint32_t& total_descriptors_number,
|
||||
uint32_t& version,
|
||||
profiler::processid_t& pid,
|
||||
bool gather_statistics,
|
||||
std::ostream& _log)
|
||||
{
|
||||
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, total_descriptors_number, version, gather_statistics, _log);
|
||||
std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks,
|
||||
threaded_trees, total_descriptors_number, version, pid, gather_statistics, _log);
|
||||
}
|
||||
|
||||
inline bool readDescriptionsFromStream(::std::stringstream& str,
|
||||
::profiler::SerializedData& serialized_descriptors,
|
||||
::profiler::descriptors_list_t& descriptors,
|
||||
::std::stringstream& _log)
|
||||
inline profiler::block_index_t writeTreesToFile(const char* filename,
|
||||
const profiler::SerializedData& serialized_descriptors,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_t descriptors_count,
|
||||
const profiler::thread_blocks_tree_t& trees,
|
||||
profiler::block_getter_fn block_getter,
|
||||
profiler::timestamp_t begin_time,
|
||||
profiler::timestamp_t end_time,
|
||||
profiler::processid_t pid,
|
||||
std::ostream& log)
|
||||
{
|
||||
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
return writeTreesToFile(progress, filename, serialized_descriptors, descriptors, descriptors_count, trees,
|
||||
std::move(block_getter), begin_time, end_time, pid, log);
|
||||
}
|
||||
|
||||
inline profiler::block_index_t writeTreesToStream(std::ostream& str,
|
||||
const profiler::SerializedData& serialized_descriptors,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_t descriptors_count,
|
||||
const profiler::thread_blocks_tree_t& trees,
|
||||
profiler::block_getter_fn block_getter,
|
||||
profiler::timestamp_t begin_time,
|
||||
profiler::timestamp_t end_time,
|
||||
profiler::processid_t pid,
|
||||
std::ostream& log)
|
||||
{
|
||||
std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
return writeTreesToStream(progress, str, serialized_descriptors, descriptors, descriptors_count, trees,
|
||||
std::move(block_getter), begin_time, end_time, pid, log);
|
||||
}
|
||||
|
||||
inline bool readDescriptionsFromStream(std::istream& str,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
std::ostream& _log)
|
||||
{
|
||||
std::atomic<int> progress = ATOMIC_VAR_INIT(0);
|
||||
return readDescriptionsFromStream(progress, str, serialized_descriptors, descriptors, _log);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ The Apache License, Version 2.0 (the "License");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint64_t processid_t;
|
||||
using processid_t = uint64_t;
|
||||
|
||||
class BlockDescriptor;
|
||||
|
||||
@ -79,14 +79,15 @@ class ProfileManager
|
||||
|
||||
ProfileManager();
|
||||
|
||||
typedef profiler::guard_lock<profiler::spin_lock> guard_lock_t;
|
||||
typedef std::map<profiler::thread_id_t, ThreadStorage> map_of_threads_stacks;
|
||||
typedef std::vector<BlockDescriptor*> block_descriptors_t;
|
||||
using atomic_timestamp_t = std::atomic<profiler::timestamp_t>;
|
||||
using guard_lock_t = profiler::guard_lock<profiler::spin_lock>;
|
||||
using map_of_threads_stacks = std::map<profiler::thread_id_t, ThreadStorage>;
|
||||
using block_descriptors_t = std::vector<BlockDescriptor*>;
|
||||
|
||||
#ifdef EASY_PROFILER_HASHED_CSTR_DEFINED
|
||||
typedef std::unordered_map<profiler::hashed_cstr, profiler::block_id_t> descriptors_map_t;
|
||||
using descriptors_map_t = std::unordered_map<profiler::hashed_cstr, profiler::block_id_t>;
|
||||
#else
|
||||
typedef std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t> descriptors_map_t;
|
||||
using descriptors_map_t = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
|
||||
#endif
|
||||
|
||||
const processid_t m_processId;
|
||||
@ -97,9 +98,9 @@ class ProfileManager
|
||||
uint64_t m_descriptorsMemorySize;
|
||||
profiler::timestamp_t m_beginTime;
|
||||
profiler::timestamp_t m_endTime;
|
||||
std::atomic<profiler::timestamp_t> m_frameMax;
|
||||
std::atomic<profiler::timestamp_t> m_frameAvg;
|
||||
std::atomic<profiler::timestamp_t> m_frameCur;
|
||||
atomic_timestamp_t m_frameMax;
|
||||
atomic_timestamp_t m_frameAvg;
|
||||
atomic_timestamp_t m_frameCur;
|
||||
profiler::spin_lock m_spin;
|
||||
profiler::spin_lock m_storedSpin;
|
||||
profiler::spin_lock m_dumpSpin;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -407,6 +407,8 @@ void BlocksGraphicsView::clear()
|
||||
|
||||
EASY_GLOBALS.selected_thread = 0;
|
||||
emit EASY_GLOBALS.events.selectedThreadChanged(0);
|
||||
|
||||
emit EASY_GLOBALS.events.rulerVisible(false);
|
||||
}
|
||||
|
||||
void BlocksGraphicsView::notifySceneSizeChange()
|
||||
@ -438,7 +440,10 @@ void BlocksGraphicsView::notifyVisibleRegionPosChange()
|
||||
|
||||
void BlocksGraphicsView::notifyVisibleRegionPosChange(qreal _pos)
|
||||
{
|
||||
m_offset = estd::clamp(0., _pos, m_sceneWidth - m_visibleRegionWidth);
|
||||
if (m_sceneWidth < m_visibleRegionWidth)
|
||||
m_offset = 0;
|
||||
else
|
||||
m_offset = estd::clamp(0., _pos, m_sceneWidth - m_visibleRegionWidth);
|
||||
notifyVisibleRegionPosChange();
|
||||
}
|
||||
|
||||
@ -614,6 +619,21 @@ const BlocksGraphicsView::Items &BlocksGraphicsView::getItems() const
|
||||
return m_items;
|
||||
}
|
||||
|
||||
bool BlocksGraphicsView::getSelectionRegionForSaving(profiler::timestamp_t& _beginTime, profiler::timestamp_t& _endTime) const
|
||||
{
|
||||
if (m_bEmpty)
|
||||
return false;
|
||||
|
||||
if (!m_selectionItem->isVisible() && !m_rulerItem->isVisible())
|
||||
return false;
|
||||
|
||||
decltype(m_selectionItem) ruler = m_selectionItem->isVisible() ? m_selectionItem : m_rulerItem;
|
||||
_beginTime = m_beginTime + position2time(ruler->left());
|
||||
_endTime = m_beginTime + position2time(ruler->right());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qreal BlocksGraphicsView::setTree(BlocksGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, uint32_t& _maxDepthChild, qreal _y, short _level)
|
||||
{
|
||||
if (_children.empty())
|
||||
@ -898,7 +918,10 @@ void BlocksGraphicsView::onWheel(qreal _scenePos, int _wheelDelta)
|
||||
notifyVisibleRegionSizeChange();
|
||||
|
||||
// Calculate new offset to simulate QGraphicsView::AnchorUnderMouse scaling behavior
|
||||
m_offset = clamp(0., initialPosition - _scenePos / m_scale, m_sceneWidth - m_visibleRegionWidth);
|
||||
if (m_sceneWidth < m_visibleRegionWidth)
|
||||
m_offset = 0;
|
||||
else
|
||||
m_offset = clamp(0., initialPosition - _scenePos / m_scale, m_sceneWidth - m_visibleRegionWidth);
|
||||
|
||||
// Update slider position
|
||||
profiler_gui::BoolFlagGuard guard(m_bUpdatingRect, true); // To be sure that updateVisibleSceneRect will not be called by scrollbar change
|
||||
@ -955,6 +978,7 @@ void BlocksGraphicsView::mousePressEvent(QMouseEvent* _event)
|
||||
m_selectionItem->setLeftRight(mouseX, mouseX);
|
||||
m_selectionItem->hide();
|
||||
m_pScrollbar->hideSelectionIndicator();
|
||||
emit EASY_GLOBALS.events.rulerVisible(m_rulerItem->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
@ -984,6 +1008,7 @@ void BlocksGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
|
||||
m_rulerItem->setLeftRight(mouseX, mouseX);
|
||||
m_rulerItem->hide();
|
||||
emit sceneUpdated();
|
||||
emit EASY_GLOBALS.events.rulerVisible(m_selectionItem->isVisible());
|
||||
}
|
||||
|
||||
_event->accept();
|
||||
@ -1010,6 +1035,7 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
|
||||
{
|
||||
m_selectionItem->hide();
|
||||
m_pScrollbar->hideSelectionIndicator();
|
||||
emit EASY_GLOBALS.events.rulerVisible(m_rulerItem->isVisible());
|
||||
}
|
||||
|
||||
if (!m_selectedBlocks.empty())
|
||||
@ -1046,6 +1072,7 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
|
||||
{
|
||||
chronoHidden = true;
|
||||
m_rulerItem->hide();
|
||||
emit EASY_GLOBALS.events.rulerVisible(m_selectionItem->isVisible());
|
||||
}
|
||||
else if (m_selectionItem->isVisible() && m_selectionItem->hoverIndicator())
|
||||
{
|
||||
@ -1191,6 +1218,9 @@ void BlocksGraphicsView::addSelectionToHierarchy()
|
||||
|
||||
void BlocksGraphicsView::onZoomSelection()
|
||||
{
|
||||
if (m_selectionItem->width() < 1e-6)
|
||||
return;
|
||||
|
||||
auto deltaScale = m_visibleRegionWidth / m_selectionItem->width();
|
||||
|
||||
if (fabs(deltaScale - 1) < 1e-6)
|
||||
@ -1229,6 +1259,9 @@ void BlocksGraphicsView::onInspectCurrentView(bool _strict)
|
||||
m_selectionItem->show();
|
||||
m_pScrollbar->setSelectionPos(m_selectionItem->left(), m_selectionItem->right());
|
||||
m_pScrollbar->showSelectionIndicator();
|
||||
|
||||
emit EASY_GLOBALS.events.rulerVisible(true);
|
||||
|
||||
addSelectionToHierarchy();
|
||||
}
|
||||
else
|
||||
@ -1281,6 +1314,7 @@ bool BlocksGraphicsView::moveChrono(GraphicsRulerItem* _chronometerItem, qreal _
|
||||
if (!_chronometerItem->isVisible() && _chronometerItem->width() > 1e-6)
|
||||
{
|
||||
_chronometerItem->show();
|
||||
emit EASY_GLOBALS.events.rulerVisible(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,8 @@ public:
|
||||
|
||||
const Items& getItems() const;
|
||||
|
||||
bool getSelectionRegionForSaving(profiler::timestamp_t& _beginTime, profiler::timestamp_t& _endTime) const;
|
||||
|
||||
void inspectCurrentView(bool _strict) {
|
||||
onInspectCurrentView(_strict);
|
||||
}
|
||||
|
@ -122,8 +122,6 @@ struct EasyBlock Q_DECL_FINAL
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
EasyBlock(const EasyBlock&) = delete;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
@ -79,6 +79,7 @@ namespace profiler_gui {
|
||||
|
||||
Globals::Globals()
|
||||
: theme("default")
|
||||
, pid(0)
|
||||
, begin_time(0)
|
||||
, selected_thread(0U)
|
||||
, selected_block(::profiler_gui::numeric_max<decltype(selected_block)>())
|
||||
|
@ -204,6 +204,7 @@ namespace profiler_gui {
|
||||
|
||||
SceneData scene; ///< Diagram scene sizes and visible area position
|
||||
SizeGuide size; ///< Various widgets and font sizes adapted to current device pixel ratio
|
||||
::profiler::processid_t pid; ///< Profiled process ID
|
||||
::profiler::timestamp_t begin_time; ///< Timestamp of the most left diagram scene point (x=0)
|
||||
::profiler::thread_id_t selected_thread; ///< Current selected thread id
|
||||
::profiler::block_index_t selected_block; ///< Current selected profiler block index
|
||||
@ -263,6 +264,10 @@ inline profiler::SerializedBlockDescriptor& easyDescriptor(profiler::block_id_t
|
||||
return *EASY_GLOBALS.descriptors[i];
|
||||
}
|
||||
|
||||
inline profiler::SerializedBlockDescriptor& easyDescriptor(const profiler::BlocksTree& _block) {
|
||||
return easyDescriptor(_block.node->id());
|
||||
}
|
||||
|
||||
EASY_FORCE_INLINE const profiler::BlocksTree& easyBlocksTree(profiler::block_index_t i) {
|
||||
return easyBlock(i).tree;
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ namespace profiler_gui {
|
||||
void hexThreadIdChanged();
|
||||
void refreshRequired();
|
||||
void blocksTreeModeChanged();
|
||||
void rulerVisible(bool);
|
||||
|
||||
void sceneCleared();
|
||||
void sceneSizeChanged(qreal left, qreal right);
|
||||
|
@ -42,6 +42,7 @@ default/arrow-up-hover.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/arrow-up-disabled.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/arrow-left.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/arrow-right.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/crop.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/yx.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/svg2.svg - Icon made by Freepik from www.flaticon.com
|
||||
default/svg3.svg - Icon made by Freepik from www.flaticon.com
|
||||
|
15
profiler_gui/images/default/crop.svg
Normal file
15
profiler_gui/images/default/crop.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!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="956.815px" height="956.815px" viewBox="0 0 956.815 956.815" style="enable-background:new 0 0 956.815 956.815;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#484848" d="M137.621,162.622H20c-11.046,0-20,8.954-20,20v72.919c0,11.046,8.954,20,20,20h117.622L137.621,162.622L137.621,162.622z"/>
|
||||
<path fill="#484848" d="M774.193,956.815c11.046,0,20-8.954,20-20V819.193H681.274v117.621c0,11.046,8.954,20,20,20L774.193,956.815
|
||||
L774.193,956.815z"/>
|
||||
<path fill="#484848" d="M794.193,656.275V182.622c0-11.046-8.954-20-20-20H300.54v112.919h380.734v380.734H794.193z"/>
|
||||
<path fill="#f44336" d="M936.814,681.275H794.193H681.274H275.54V275.541V162.622V20c0-11.046-8.954-20-20-20h-72.918c-11.046,0-20,8.954-20,20
|
||||
v142.622v112.919v498.653c0,11.046,8.954,20,20,20h498.653h112.918h142.622c11.045,0,20-8.954,20-20v-72.918
|
||||
C956.814,690.229,947.86,681.275,936.814,681.275z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -250,7 +250,7 @@ void MainWindow::configureSizes()
|
||||
w.hide();
|
||||
}
|
||||
|
||||
MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhost"), m_lastPort(::profiler::DEFAULT_PORT)
|
||||
MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhost"), m_lastPort(profiler::DEFAULT_PORT)
|
||||
{
|
||||
{ QIcon icon(":/images/logo"); if (!icon.isNull()) QApplication::setWindowIcon(icon); }
|
||||
|
||||
@ -378,6 +378,12 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
static_cast<DiagramWidget*>(m_graphicsView->widget())->view()->inspectCurrentView(true);
|
||||
});
|
||||
|
||||
action = toolbar->addAction(QIcon(imagePath("crop")), "Snapshot");
|
||||
action->setToolTip("Take a snapshot.\nSave selected area to\nseparate .prof file.");
|
||||
action->setEnabled(false);
|
||||
connect(action, &QAction::triggered, this, &This::onSnapshotClicked);
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::rulerVisible, action, &QAction::setEnabled);
|
||||
|
||||
toolbar->addSeparator();
|
||||
auto menu = new QMenu("Settings", this);
|
||||
menu->setToolTipsVisible(true);
|
||||
@ -547,8 +553,8 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
action = new QAction("Chrono text at top", actionGroup);
|
||||
action->setToolTip("Draw duration of selected interval\nat the top of the screen.");
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Top));
|
||||
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
|
||||
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);
|
||||
@ -556,8 +562,8 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
action = new QAction("Chrono text at center", actionGroup);
|
||||
action->setToolTip("Draw duration of selected interval\nat the center of the screen.");
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Center));
|
||||
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
|
||||
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);
|
||||
@ -565,8 +571,8 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
action = new QAction("Chrono text at bottom", actionGroup);
|
||||
action->setToolTip("Draw duration of selected interval\nat the bottom of the screen.");
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::ChronoTextPosition_Bottom));
|
||||
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
|
||||
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);
|
||||
@ -674,32 +680,32 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
actionGroup->setExclusive(true);
|
||||
action = new QAction("Auto", actionGroup);
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::TimeUnits_auto));
|
||||
if (EASY_GLOBALS.time_units == ::profiler_gui::TimeUnits_auto)
|
||||
action->setData(static_cast<int>(profiler_gui::TimeUnits_auto));
|
||||
if (EASY_GLOBALS.time_units == profiler_gui::TimeUnits_auto)
|
||||
action->setChecked(true);
|
||||
submenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, &This::onUnitsChanged);
|
||||
|
||||
action = new QAction("Milliseconds", actionGroup);
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::TimeUnits_ms));
|
||||
if (EASY_GLOBALS.time_units == ::profiler_gui::TimeUnits_ms)
|
||||
action->setData(static_cast<int>(profiler_gui::TimeUnits_ms));
|
||||
if (EASY_GLOBALS.time_units == profiler_gui::TimeUnits_ms)
|
||||
action->setChecked(true);
|
||||
submenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, &This::onUnitsChanged);
|
||||
|
||||
action = new QAction("Microseconds", actionGroup);
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::TimeUnits_us));
|
||||
if (EASY_GLOBALS.time_units == ::profiler_gui::TimeUnits_us)
|
||||
action->setData(static_cast<int>(profiler_gui::TimeUnits_us));
|
||||
if (EASY_GLOBALS.time_units == profiler_gui::TimeUnits_us)
|
||||
action->setChecked(true);
|
||||
submenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, &This::onUnitsChanged);
|
||||
|
||||
action = new QAction("Nanoseconds", actionGroup);
|
||||
action->setCheckable(true);
|
||||
action->setData(static_cast<int>(::profiler_gui::TimeUnits_ns));
|
||||
if (EASY_GLOBALS.time_units == ::profiler_gui::TimeUnits_ns)
|
||||
action->setData(static_cast<int>(profiler_gui::TimeUnits_ns));
|
||||
if (EASY_GLOBALS.time_units == profiler_gui::TimeUnits_ns)
|
||||
action->setChecked(true);
|
||||
submenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, &This::onUnitsChanged);
|
||||
@ -789,13 +795,14 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
|
||||
m_frameTimeEdit->setValidator(val);
|
||||
m_frameTimeEdit->setText(QString::number(EASY_GLOBALS.frame_time * 1e-3));
|
||||
connect(m_frameTimeEdit, &QLineEdit::editingFinished, this, &This::onFrameTimeEditFinish);
|
||||
connect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::expectedFrameTimeChanged, this, &This::onFrameTimeChanged);
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged, this, &This::onFrameTimeChanged);
|
||||
toolbar->addWidget(m_frameTimeEdit);
|
||||
|
||||
lbl = new QLabel("ms", toolbar);
|
||||
lbl->setContentsMargins(5, 2, 1, 1);
|
||||
toolbar->addWidget(lbl);
|
||||
|
||||
m_readerTimer.setInterval(LOADER_TIMER_INTERVAL);
|
||||
|
||||
connect(graphicsView->view(), &BlocksGraphicsView::intervalChanged, treeWidget->tree(), &BlocksTreeWidget::setTreeBlocks);
|
||||
connect(&m_readerTimer, &QTimer::timeout, this, &This::onFileReaderTimeout);
|
||||
@ -962,14 +969,14 @@ void MainWindow::loadFile(const QString& filename)
|
||||
|
||||
createProgressDialog(QString("Loading %1...").arg(filename.mid(std::max(i, j) + 1)));
|
||||
|
||||
m_readerTimer.start(LOADER_TIMER_INTERVAL);
|
||||
m_readerTimer.start();
|
||||
m_reader.load(filename);
|
||||
}
|
||||
|
||||
void MainWindow::readStream(std::stringstream& _data)
|
||||
{
|
||||
createProgressDialog(tr("Reading from stream..."));
|
||||
m_readerTimer.start(LOADER_TIMER_INTERVAL);
|
||||
m_readerTimer.start();
|
||||
m_reader.load(_data);
|
||||
}
|
||||
|
||||
@ -1117,8 +1124,8 @@ void MainWindow::clear()
|
||||
emit EASY_GLOBALS.events.allDataGoingToBeDeleted();
|
||||
|
||||
EASY_GLOBALS.selected_thread = 0;
|
||||
::profiler_gui::set_max(EASY_GLOBALS.selected_block);
|
||||
::profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
|
||||
profiler_gui::set_max(EASY_GLOBALS.selected_block);
|
||||
profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
|
||||
EASY_GLOBALS.profiler_blocks.clear();
|
||||
EASY_GLOBALS.descriptors.clear();
|
||||
EASY_GLOBALS.gui_blocks.clear();
|
||||
@ -1181,14 +1188,14 @@ void MainWindow::onEncodingChanged(bool)
|
||||
void MainWindow::onChronoTextPosChanged(bool)
|
||||
{
|
||||
auto _sender = qobject_cast<QAction*>(sender());
|
||||
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(_sender->data().toInt());
|
||||
EASY_GLOBALS.chrono_text_position = static_cast<profiler_gui::ChronometerTextPosition>(_sender->data().toInt());
|
||||
refreshDiagram();
|
||||
}
|
||||
|
||||
void MainWindow::onUnitsChanged(bool)
|
||||
{
|
||||
auto _sender = qobject_cast<QAction*>(sender());
|
||||
EASY_GLOBALS.time_units = static_cast<::profiler_gui::TimeUnits>(_sender->data().toInt());
|
||||
EASY_GLOBALS.time_units = static_cast<profiler_gui::TimeUnits>(_sender->data().toInt());
|
||||
}
|
||||
|
||||
void MainWindow::onEnableDisableStatistics(bool _checked)
|
||||
@ -1379,7 +1386,7 @@ void MainWindow::closeEvent(QCloseEvent* close_event)
|
||||
|
||||
void MainWindow::loadSettings()
|
||||
{
|
||||
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
|
||||
QSettings settings(profiler_gui::ORGANAZATION_NAME, profiler_gui::APPLICATION_NAME);
|
||||
settings.beginGroup("main");
|
||||
|
||||
auto last_files = settings.value("last_files");
|
||||
@ -1400,11 +1407,11 @@ void MainWindow::loadSettings()
|
||||
|
||||
auto val = settings.value("chrono_text_position");
|
||||
if (!val.isNull())
|
||||
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(val.toInt());
|
||||
EASY_GLOBALS.chrono_text_position = static_cast<profiler_gui::ChronometerTextPosition>(val.toInt());
|
||||
|
||||
val = settings.value("time_units");
|
||||
if (!val.isNull())
|
||||
EASY_GLOBALS.time_units = static_cast<::profiler_gui::TimeUnits>(val.toInt());
|
||||
EASY_GLOBALS.time_units = static_cast<profiler_gui::TimeUnits>(val.toInt());
|
||||
|
||||
|
||||
val = settings.value("frame_time");
|
||||
@ -1529,7 +1536,7 @@ void MainWindow::loadSettings()
|
||||
|
||||
void MainWindow::loadGeometry()
|
||||
{
|
||||
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
|
||||
QSettings settings(profiler_gui::ORGANAZATION_NAME, profiler_gui::APPLICATION_NAME);
|
||||
settings.beginGroup("main");
|
||||
|
||||
auto geometry = settings.value("geometry").toByteArray();
|
||||
@ -1559,7 +1566,7 @@ void MainWindow::loadGeometry()
|
||||
|
||||
void MainWindow::saveSettingsAndGeometry()
|
||||
{
|
||||
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
|
||||
QSettings settings(profiler_gui::ORGANAZATION_NAME, profiler_gui::APPLICATION_NAME);
|
||||
settings.beginGroup("main");
|
||||
|
||||
settings.setValue("geometry", this->saveGeometry());
|
||||
@ -1838,123 +1845,162 @@ void MainWindow::onListenerDialogClose(int _result)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MainWindow::closeProgressDialogAndClearReader()
|
||||
{
|
||||
m_reader.interrupt();
|
||||
m_readerTimer.stop();
|
||||
destroyProgressDialog();
|
||||
}
|
||||
|
||||
void MainWindow::onLoadingFinish(profiler::block_index_t& _nblocks)
|
||||
{
|
||||
_nblocks = m_reader.size();
|
||||
if (_nblocks != 0)
|
||||
{
|
||||
emit EASY_GLOBALS.events.allDataGoingToBeDeleted();
|
||||
|
||||
profiler::SerializedData serialized_blocks;
|
||||
profiler::SerializedData serialized_descriptors;
|
||||
profiler::descriptors_list_t descriptors;
|
||||
profiler::blocks_t blocks;
|
||||
profiler::thread_blocks_tree_t threads_map;
|
||||
QString filename;
|
||||
uint32_t descriptorsNumberInFile = 0;
|
||||
uint32_t version = 0;
|
||||
profiler::processid_t pid = 0;
|
||||
|
||||
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map,
|
||||
descriptorsNumberInFile, version, pid, filename);
|
||||
|
||||
if (threads_map.size() > 0xff)
|
||||
{
|
||||
if (m_reader.isFile())
|
||||
qWarning() << "Warning: file " << filename << " contains " << threads_map.size() << " threads!";
|
||||
else
|
||||
qWarning() << "Warning: input stream contains " << threads_map.size() << " threads!";
|
||||
qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed.";
|
||||
}
|
||||
|
||||
m_bNetworkFileRegime = !m_reader.isFile();
|
||||
if (!m_bNetworkFileRegime)
|
||||
{
|
||||
auto index = m_lastFiles.indexOf(filename, 0);
|
||||
if (index == -1)
|
||||
{
|
||||
// This file is totally new. Add it to the list.
|
||||
addFileToList(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index != 0)
|
||||
{
|
||||
// This file has been already loaded. Move it to the front.
|
||||
m_lastFiles.move(index, 0);
|
||||
auto fileActions = m_loadActionMenu->actions();
|
||||
auto action = fileActions.at(index);
|
||||
m_loadActionMenu->removeAction(action);
|
||||
m_loadActionMenu->insertAction(fileActions.front(), action);
|
||||
validateLastDir();
|
||||
}
|
||||
|
||||
m_bOpenedCacheFile = filename.contains(NETWORK_CACHE_FILE);
|
||||
|
||||
if (m_bOpenedCacheFile)
|
||||
setWindowTitle(QString(EASY_DEFAULT_WINDOW_TITLE " - [%1] - UNSAVED network cache file").arg(filename));
|
||||
else
|
||||
setWindowTitle(QString(EASY_DEFAULT_WINDOW_TITLE " - [%1]").arg(filename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bOpenedCacheFile = false;
|
||||
setWindowTitle(EASY_DEFAULT_WINDOW_TITLE " - UNSAVED network cache");
|
||||
}
|
||||
|
||||
m_serializedBlocks = std::move(serialized_blocks);
|
||||
m_serializedDescriptors = std::move(serialized_descriptors);
|
||||
m_descriptorsNumberInFile = descriptorsNumberInFile;
|
||||
EASY_GLOBALS.selected_thread = 0;
|
||||
EASY_GLOBALS.version = version;
|
||||
EASY_GLOBALS.pid = pid;
|
||||
profiler_gui::set_max(EASY_GLOBALS.selected_block);
|
||||
profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
|
||||
EASY_GLOBALS.profiler_blocks.swap(threads_map);
|
||||
EASY_GLOBALS.descriptors.swap(descriptors);
|
||||
|
||||
EASY_GLOBALS.gui_blocks.clear();
|
||||
EASY_GLOBALS.gui_blocks.resize(_nblocks);
|
||||
memset(EASY_GLOBALS.gui_blocks.data(), 0, sizeof(profiler_gui::EasyBlock) * _nblocks);
|
||||
|
||||
for (std::remove_reference<decltype(_nblocks)>::type i = 0; i < _nblocks; ++i)
|
||||
{
|
||||
auto& guiblock = EASY_GLOBALS.gui_blocks[i];
|
||||
guiblock.tree = std::move(blocks[i]);
|
||||
#ifdef EASY_TREE_WIDGET__USE_VECTOR
|
||||
profiler_gui::set_max(guiblock.tree_item);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_saveAction->setEnabled(true);
|
||||
m_deleteAction->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", QString("Cannot read profiled blocks.\n\nReason:\n%1")
|
||||
.arg(m_reader.getError()), QMessageBox::Close);
|
||||
|
||||
if (m_reader.isFile())
|
||||
{
|
||||
auto index = m_lastFiles.indexOf(m_reader.filename(), 0);
|
||||
if (index >= 0)
|
||||
{
|
||||
// Remove unexisting file from list
|
||||
m_lastFiles.removeAt(index);
|
||||
auto action = m_loadActionMenu->actions().at(index);
|
||||
m_loadActionMenu->removeAction(action);
|
||||
delete action;
|
||||
validateLastDir();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onSavingFinish()
|
||||
{
|
||||
const auto errorMessage = m_reader.getError();
|
||||
if (!errorMessage.isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", QString("Cannot save profiled blocks.\n\nReason:\n%1")
|
||||
.arg(errorMessage), QMessageBox::Close);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onFileReaderTimeout()
|
||||
{
|
||||
if (m_reader.done())
|
||||
{
|
||||
const auto nblocks = m_reader.size();
|
||||
if (nblocks != 0)
|
||||
if (m_reader.isLoading())
|
||||
{
|
||||
emit EASY_GLOBALS.events.allDataGoingToBeDeleted();
|
||||
profiler::block_index_t nblocks = 0;
|
||||
|
||||
::profiler::SerializedData serialized_blocks;
|
||||
::profiler::SerializedData serialized_descriptors;
|
||||
::profiler::descriptors_list_t descriptors;
|
||||
::profiler::blocks_t blocks;
|
||||
::profiler::thread_blocks_tree_t threads_map;
|
||||
QString filename;
|
||||
uint32_t descriptorsNumberInFile = 0;
|
||||
uint32_t version = 0;
|
||||
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, descriptorsNumberInFile, version, filename);
|
||||
onLoadingFinish(nblocks);
|
||||
closeProgressDialogAndClearReader();
|
||||
|
||||
if (threads_map.size() > 0xff)
|
||||
if (nblocks != 0)
|
||||
{
|
||||
if (m_reader.isFile())
|
||||
qWarning() << "Warning: file " << filename << " contains " << threads_map.size() << " threads!";
|
||||
else
|
||||
qWarning() << "Warning: input stream contains " << threads_map.size() << " threads!";
|
||||
qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed.";
|
||||
emit EASY_GLOBALS.events.fileOpened();
|
||||
if (EASY_GLOBALS.all_items_expanded_by_default)
|
||||
onExpandAllClicked(true);
|
||||
}
|
||||
|
||||
m_bNetworkFileRegime = !m_reader.isFile();
|
||||
if (!m_bNetworkFileRegime)
|
||||
{
|
||||
auto index = m_lastFiles.indexOf(filename, 0);
|
||||
if (index == -1)
|
||||
{
|
||||
// This file is totally new. Add it to the list.
|
||||
addFileToList(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index != 0)
|
||||
{
|
||||
// This file has been already loaded. Move it to the front.
|
||||
m_lastFiles.move(index, 0);
|
||||
auto fileActions = m_loadActionMenu->actions();
|
||||
auto action = fileActions.at(index);
|
||||
m_loadActionMenu->removeAction(action);
|
||||
m_loadActionMenu->insertAction(fileActions.front(), action);
|
||||
validateLastDir();
|
||||
}
|
||||
|
||||
m_bOpenedCacheFile = filename.contains(NETWORK_CACHE_FILE);
|
||||
|
||||
if (m_bOpenedCacheFile)
|
||||
setWindowTitle(QString(EASY_DEFAULT_WINDOW_TITLE " - [%1] - UNSAVED network cache file").arg(filename));
|
||||
else
|
||||
setWindowTitle(QString(EASY_DEFAULT_WINDOW_TITLE " - [%1]").arg(filename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bOpenedCacheFile = false;
|
||||
setWindowTitle(EASY_DEFAULT_WINDOW_TITLE " - UNSAVED network cache");
|
||||
}
|
||||
|
||||
m_serializedBlocks = std::move(serialized_blocks);
|
||||
m_serializedDescriptors = std::move(serialized_descriptors);
|
||||
m_descriptorsNumberInFile = descriptorsNumberInFile;
|
||||
EASY_GLOBALS.selected_thread = 0;
|
||||
EASY_GLOBALS.version = version;
|
||||
::profiler_gui::set_max(EASY_GLOBALS.selected_block);
|
||||
::profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
|
||||
EASY_GLOBALS.profiler_blocks.swap(threads_map);
|
||||
EASY_GLOBALS.descriptors.swap(descriptors);
|
||||
|
||||
EASY_GLOBALS.gui_blocks.clear();
|
||||
EASY_GLOBALS.gui_blocks.resize(nblocks);
|
||||
memset(EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::EasyBlock) * nblocks);
|
||||
for (std::remove_const<decltype(nblocks)>::type i = 0; i < nblocks; ++i) {
|
||||
auto& guiblock = EASY_GLOBALS.gui_blocks[i];
|
||||
guiblock.tree = std::move(blocks[i]);
|
||||
#ifdef EASY_TREE_WIDGET__USE_VECTOR
|
||||
::profiler_gui::set_max(guiblock.tree_item);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_saveAction->setEnabled(true);
|
||||
m_deleteAction->setEnabled(true);
|
||||
}
|
||||
else if (m_reader.isSaving())
|
||||
{
|
||||
onSavingFinish();
|
||||
closeProgressDialogAndClearReader();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", QString("Cannot read profiled blocks.\n\nReason:\n%1").arg(m_reader.getError()), QMessageBox::Close);
|
||||
|
||||
if (m_reader.isFile())
|
||||
{
|
||||
auto index = m_lastFiles.indexOf(m_reader.filename(), 0);
|
||||
if (index >= 0)
|
||||
{
|
||||
// Remove unexisting file from list
|
||||
m_lastFiles.removeAt(index);
|
||||
auto action = m_loadActionMenu->actions().at(index);
|
||||
m_loadActionMenu->removeAction(action);
|
||||
delete action;
|
||||
validateLastDir();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_reader.interrupt();
|
||||
|
||||
m_readerTimer.stop();
|
||||
destroyProgressDialog();
|
||||
|
||||
if (nblocks != 0)
|
||||
{
|
||||
emit EASY_GLOBALS.events.fileOpened();
|
||||
if (EASY_GLOBALS.all_items_expanded_by_default)
|
||||
onExpandAllClicked(true);
|
||||
closeProgressDialogAndClearReader();
|
||||
}
|
||||
}
|
||||
else if (m_progress != nullptr)
|
||||
@ -1987,6 +2033,16 @@ const bool FileReader::isFile() const
|
||||
return m_isFile;
|
||||
}
|
||||
|
||||
const bool FileReader::isSaving() const
|
||||
{
|
||||
return m_jobType == JobType::Saving;
|
||||
}
|
||||
|
||||
const bool FileReader::isLoading() const
|
||||
{
|
||||
return m_jobType == JobType::Loading;
|
||||
}
|
||||
|
||||
bool FileReader::done() const
|
||||
{
|
||||
return m_bDone.load(std::memory_order_acquire);
|
||||
@ -2011,13 +2067,20 @@ void FileReader::load(const QString& _filename)
|
||||
{
|
||||
interrupt();
|
||||
|
||||
m_jobType = JobType::Loading;
|
||||
m_isFile = true;
|
||||
m_filename = _filename;
|
||||
m_thread = 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, m_descriptorsNumberInFile, m_version, _enableStatistics, m_errorMessage), std::memory_order_release);
|
||||
|
||||
m_thread = 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,
|
||||
m_descriptorsNumberInFile, m_version, m_pid, _enableStatistics,
|
||||
m_errorMessage), std::memory_order_release);
|
||||
|
||||
m_progress.store(100, std::memory_order_release);
|
||||
m_bDone.store(true, std::memory_order_release);
|
||||
|
||||
}, EASY_GLOBALS.enable_statistics);
|
||||
}
|
||||
|
||||
@ -2025,6 +2088,7 @@ void FileReader::load(std::stringstream& _stream)
|
||||
{
|
||||
interrupt();
|
||||
|
||||
m_jobType = JobType::Loading;
|
||||
m_isFile = false;
|
||||
m_filename.clear();
|
||||
|
||||
@ -2038,19 +2102,72 @@ void FileReader::load(std::stringstream& _stream)
|
||||
m_stream.swap(_stream);
|
||||
#endif
|
||||
|
||||
m_thread = std::thread([this](bool _enableStatistics) {
|
||||
m_thread = std::thread([this](bool _enableStatistics)
|
||||
{
|
||||
std::ofstream cache_file(NETWORK_CACHE_FILE, std::fstream::binary);
|
||||
if (cache_file.is_open()) {
|
||||
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, m_version, _enableStatistics, m_errorMessage), std::memory_order_release);
|
||||
|
||||
m_size.store(fillTreesFromStream(m_progress, m_stream, m_serializedBlocks, m_serializedDescriptors,
|
||||
m_descriptors, m_blocks, m_blocksTree, m_descriptorsNumberInFile,
|
||||
m_version, m_pid, _enableStatistics, m_errorMessage), std::memory_order_release);
|
||||
|
||||
m_progress.store(100, std::memory_order_release);
|
||||
m_bDone.store(true, std::memory_order_release);
|
||||
|
||||
}, EASY_GLOBALS.enable_statistics);
|
||||
}
|
||||
|
||||
void FileReader::save(const QString& _filename, profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime,
|
||||
const profiler::SerializedData& _serializedDescriptors,
|
||||
const profiler::descriptors_list_t& _descriptors, profiler::block_id_t descriptors_count,
|
||||
const profiler::thread_blocks_tree_t& _trees, profiler::block_getter_fn block_getter,
|
||||
profiler::processid_t _pid)
|
||||
{
|
||||
interrupt();
|
||||
|
||||
m_jobType = JobType::Saving;
|
||||
m_isFile = true;
|
||||
m_filename = _filename;
|
||||
|
||||
auto serializedDescriptors = std::ref(_serializedDescriptors);
|
||||
auto descriptors = std::ref(_descriptors);
|
||||
auto trees = std::ref(_trees);
|
||||
|
||||
m_thread = std::thread([=] (profiler::block_getter_fn getter)
|
||||
{
|
||||
const QString tmpFile = m_filename + ".tmp";
|
||||
|
||||
const auto result = writeTreesToFile(m_progress, tmpFile.toStdString().c_str(), serializedDescriptors,
|
||||
descriptors, descriptors_count, trees, getter, _beginTime, _endTime,
|
||||
_pid, m_errorMessage);
|
||||
|
||||
if (result == 0 || !m_errorMessage.str().empty())
|
||||
{
|
||||
// Remove temporary file in case of error
|
||||
QFile::remove(tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove old file if exists
|
||||
{
|
||||
QFile out(m_filename);
|
||||
if (out.exists())
|
||||
out.remove();
|
||||
}
|
||||
|
||||
QFile::rename(tmpFile, m_filename);
|
||||
}
|
||||
|
||||
m_progress.store(100, std::memory_order_release);
|
||||
m_bDone.store(true, std::memory_order_release);
|
||||
|
||||
}, std::move(block_getter));
|
||||
}
|
||||
|
||||
void FileReader::interrupt()
|
||||
{
|
||||
join();
|
||||
@ -2064,25 +2181,29 @@ void FileReader::interrupt()
|
||||
m_blocksTree.clear();
|
||||
m_descriptorsNumberInFile = 0;
|
||||
m_version = 0;
|
||||
m_pid = 0;
|
||||
m_jobType = JobType::Idle;
|
||||
|
||||
clear_stream(m_stream);
|
||||
clear_stream(m_errorMessage);
|
||||
}
|
||||
|
||||
void FileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
|
||||
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks,
|
||||
::profiler::thread_blocks_tree_t& _tree, uint32_t& _descriptorsNumberInFile, uint32_t& _version, QString& _filename)
|
||||
void FileReader::get(profiler::SerializedData& _serializedBlocks, profiler::SerializedData& _serializedDescriptors,
|
||||
profiler::descriptors_list_t& _descriptors, profiler::blocks_t& _blocks,
|
||||
profiler::thread_blocks_tree_t& _trees, uint32_t& _descriptorsNumberInFile, uint32_t& _version,
|
||||
profiler::processid_t& _pid, QString& _filename)
|
||||
{
|
||||
if (done())
|
||||
{
|
||||
m_serializedBlocks.swap(_serializedBlocks);
|
||||
m_serializedDescriptors.swap(_serializedDescriptors);
|
||||
::profiler::descriptors_list_t(std::move(m_descriptors)).swap(_descriptors);
|
||||
profiler::descriptors_list_t(std::move(m_descriptors)).swap(_descriptors);
|
||||
m_blocks.swap(_blocks);
|
||||
m_blocksTree.swap(_tree);
|
||||
m_blocksTree.swap(_trees);
|
||||
m_filename.swap(_filename);
|
||||
_descriptorsNumberInFile = m_descriptorsNumberInFile;
|
||||
_version = m_version;
|
||||
_pid = m_pid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2126,12 +2247,12 @@ void MainWindow::onFrameTimeEditFinish()
|
||||
|
||||
EASY_GLOBALS.frame_time = text.toFloat() * 1e3f;
|
||||
|
||||
disconnect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
disconnect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
this, &This::onFrameTimeChanged);
|
||||
|
||||
emit EASY_GLOBALS.events.expectedFrameTimeChanged();
|
||||
|
||||
connect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::expectedFrameTimeChanged,
|
||||
this, &This::onFrameTimeChanged);
|
||||
}
|
||||
|
||||
@ -2142,6 +2263,37 @@ void MainWindow::onFrameTimeChanged()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MainWindow::onSnapshotClicked(bool)
|
||||
{
|
||||
profiler::timestamp_t beginTime = 0, endTime = 0;
|
||||
const bool hasSelection = static_cast<DiagramWidget*>(m_graphicsView->widget())->view()->getSelectionRegionForSaving(beginTime, endTime);
|
||||
if (!hasSelection)
|
||||
return;
|
||||
|
||||
QString lastFile = m_lastFiles.empty() ? QString() : m_lastFiles.front();
|
||||
|
||||
const auto i = lastFile.lastIndexOf(QChar('/'));
|
||||
const auto j = lastFile.lastIndexOf(QChar('\\'));
|
||||
auto k = std::max(i, j);
|
||||
|
||||
QString dir;
|
||||
if (k > 0)
|
||||
dir = lastFile.mid(0, ++k);
|
||||
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save cropped area to EasyProfiler File", dir,
|
||||
"EasyProfiler File (*.prof);;All Files (*.*)");
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
createProgressDialog(tr("Saving selected region..."));
|
||||
m_readerTimer.start();
|
||||
|
||||
m_reader.save(filename, beginTime, endTime, m_serializedDescriptors, EASY_GLOBALS.descriptors,
|
||||
m_descriptorsNumberInFile, EASY_GLOBALS.profiler_blocks, easyBlocksTree, EASY_GLOBALS.pid);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MainWindow::onConnectClicked(bool)
|
||||
{
|
||||
if (EASY_GLOBALS.connected)
|
||||
@ -2428,7 +2580,7 @@ void MainWindow::onGetBlockDescriptionsClicked(bool)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MainWindow::onBlockStatusChange(::profiler::block_id_t _id, ::profiler::EasyBlockStatus _status)
|
||||
void MainWindow::onBlockStatusChange(profiler::block_id_t _id, profiler::EasyBlockStatus _status)
|
||||
{
|
||||
if (EASY_GLOBALS.connected)
|
||||
m_listener.send(profiler::net::BlockStatusMessage(_id, static_cast<uint8_t>(_status)));
|
||||
@ -2613,7 +2765,7 @@ bool SocketListener::connect(const char* _ipaddress, uint16_t _port, profiler::n
|
||||
seek += bytes;
|
||||
}
|
||||
|
||||
auto message = reinterpret_cast<const ::profiler::net::EasyProfilerStatus*>(buffer);
|
||||
auto message = reinterpret_cast<const profiler::net::EasyProfilerStatus*>(buffer);
|
||||
if (message->isEasyNetMessage() && message->type == profiler::net::MessageType::Connection_Accepted)
|
||||
_reply = *message;
|
||||
|
||||
@ -2625,7 +2777,7 @@ bool SocketListener::connect(const char* _ipaddress, uint16_t _port, profiler::n
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
bool SocketListener::reconnect(const char* _ipaddress, uint16_t _port, ::profiler::net::EasyProfilerStatus& _reply)
|
||||
bool SocketListener::reconnect(const char* _ipaddress, uint16_t _port, profiler::net::EasyProfilerStatus& _reply)
|
||||
{
|
||||
return connect(_ipaddress, _port, _reply, true);
|
||||
}
|
||||
@ -2820,7 +2972,7 @@ void SocketListener::listenCapture()
|
||||
|
||||
if (bytes > 0)
|
||||
{
|
||||
auto message = reinterpret_cast<const ::profiler::net::Message*>(buf);
|
||||
auto message = reinterpret_cast<const profiler::net::Message*>(buf);
|
||||
if (!message->isEasyNetMessage())
|
||||
continue;
|
||||
|
||||
@ -2978,7 +3130,7 @@ void SocketListener::listenDescription()
|
||||
|
||||
if (bytes > 0)
|
||||
{
|
||||
auto message = reinterpret_cast<const ::profiler::net::Message*>(buf);
|
||||
auto message = reinterpret_cast<const profiler::net::Message*>(buf);
|
||||
if (!message->isEasyNetMessage())
|
||||
continue;
|
||||
|
||||
@ -3069,7 +3221,7 @@ void SocketListener::listenDescription()
|
||||
|
||||
void SocketListener::listenFrameTime()
|
||||
{
|
||||
EASY_STATIC_CONSTEXPR size_t buffer_size = sizeof(::profiler::net::TimestampMessage) << 2;
|
||||
EASY_STATIC_CONSTEXPR size_t buffer_size = sizeof(profiler::net::TimestampMessage) << 2;
|
||||
|
||||
char buffer[buffer_size] = {};
|
||||
int seek = 0, bytes = 0;
|
||||
@ -3108,7 +3260,7 @@ void SocketListener::listenFrameTime()
|
||||
|
||||
if (bytes > 0)
|
||||
{
|
||||
auto message = reinterpret_cast<const ::profiler::net::Message*>(buf);
|
||||
auto message = reinterpret_cast<const profiler::net::Message*>(buf);
|
||||
if (!message->isEasyNetMessage())
|
||||
continue;
|
||||
|
||||
|
@ -54,10 +54,10 @@
|
||||
#ifndef EASY_PROFILER_GUI__MAIN_WINDOW__H
|
||||
#define EASY_PROFILER_GUI__MAIN_WINDOW__H
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QDockWidget>
|
||||
@ -85,6 +85,13 @@ namespace profiler { namespace net { struct EasyProfilerStatus; } }
|
||||
|
||||
class FileReader Q_DECL_FINAL
|
||||
{
|
||||
enum class JobType : int8_t
|
||||
{
|
||||
Idle=0,
|
||||
Loading,
|
||||
Saving,
|
||||
};
|
||||
|
||||
profiler::SerializedData m_serializedBlocks; ///<
|
||||
profiler::SerializedData m_serializedDescriptors; ///<
|
||||
profiler::descriptors_list_t m_descriptors; ///<
|
||||
@ -93,12 +100,14 @@ class FileReader Q_DECL_FINAL
|
||||
std::stringstream m_stream; ///<
|
||||
std::stringstream m_errorMessage; ///<
|
||||
QString m_filename; ///<
|
||||
profiler::processid_t m_pid = 0; ///<
|
||||
uint32_t m_descriptorsNumberInFile = 0; ///<
|
||||
uint32_t m_version = 0; ///<
|
||||
std::thread m_thread; ///<
|
||||
std::atomic_bool m_bDone; ///<
|
||||
std::atomic<int> m_progress; ///<
|
||||
std::atomic<unsigned int> m_size; ///<
|
||||
std::atomic<unsigned int> m_size; ///<
|
||||
JobType m_jobType = JobType::Idle; ///<
|
||||
bool m_isFile = false; ///<
|
||||
|
||||
public:
|
||||
@ -107,6 +116,9 @@ public:
|
||||
~FileReader();
|
||||
|
||||
const bool isFile() const;
|
||||
const bool isSaving() const;
|
||||
const bool isLoading() const;
|
||||
|
||||
bool done() const;
|
||||
int progress() const;
|
||||
unsigned int size() const;
|
||||
@ -114,10 +126,18 @@ public:
|
||||
|
||||
void load(const QString& _filename);
|
||||
void load(std::stringstream& _stream);
|
||||
|
||||
/** \brief Save data to file.
|
||||
*/
|
||||
void save(const QString& _filename, profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime,
|
||||
const profiler::SerializedData& _serializedDescriptors, const profiler::descriptors_list_t& _descriptors,
|
||||
profiler::block_id_t descriptors_count, const profiler::thread_blocks_tree_t& _trees,
|
||||
profiler::block_getter_fn block_getter, profiler::processid_t _pid);
|
||||
|
||||
void interrupt();
|
||||
void get(profiler::SerializedData& _serializedBlocks, profiler::SerializedData& _serializedDescriptors,
|
||||
profiler::descriptors_list_t& _descriptors, profiler::blocks_t& _blocks, profiler::thread_blocks_tree_t& _tree,
|
||||
uint32_t& _descriptorsNumberInFile, uint32_t& _version, QString& _filename);
|
||||
profiler::descriptors_list_t& _descriptors, profiler::blocks_t& _blocks, profiler::thread_blocks_tree_t& _trees,
|
||||
uint32_t& _descriptorsNumberInFile, uint32_t& _version, profiler::processid_t& _pid, QString& _filename);
|
||||
|
||||
void join();
|
||||
|
||||
@ -238,42 +258,43 @@ protected:
|
||||
QStringList m_lastFiles;
|
||||
QString m_theme;
|
||||
QString m_lastAddress;
|
||||
QDockWidget* m_treeWidget = nullptr;
|
||||
QDockWidget* m_graphicsView = nullptr;
|
||||
QDockWidget* m_fpsViewer = nullptr;
|
||||
|
||||
QDockWidget* m_treeWidget = nullptr;
|
||||
QDockWidget* m_graphicsView = nullptr;
|
||||
QDockWidget* m_fpsViewer = nullptr;
|
||||
|
||||
#if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
|
||||
QDockWidget* m_descTreeWidget = nullptr;
|
||||
#endif
|
||||
|
||||
class QProgressDialog* m_progress = nullptr;
|
||||
class BlockDescriptorsWidget* m_dialogDescTree = nullptr;
|
||||
class QMessageBox* m_listenerDialog = nullptr;
|
||||
class QProgressDialog* m_progress = nullptr;
|
||||
class BlockDescriptorsWidget* m_dialogDescTree = nullptr;
|
||||
class QMessageBox* m_listenerDialog = nullptr;
|
||||
QTimer m_readerTimer;
|
||||
QTimer m_listenerTimer;
|
||||
QTimer m_fpsRequestTimer;
|
||||
profiler::SerializedData m_serializedBlocks;
|
||||
profiler::SerializedData m_serializedDescriptors;
|
||||
FileReader m_reader;
|
||||
SocketListener m_listener;
|
||||
profiler::SerializedData m_serializedBlocks;
|
||||
profiler::SerializedData m_serializedDescriptors;
|
||||
FileReader m_reader;
|
||||
SocketListener m_listener;
|
||||
|
||||
class QLineEdit* m_addressEdit = nullptr;
|
||||
class QLineEdit* m_portEdit = nullptr;
|
||||
class QLineEdit* m_addressEdit = nullptr;
|
||||
class QLineEdit* m_portEdit = nullptr;
|
||||
class QLineEdit* m_frameTimeEdit = nullptr;
|
||||
|
||||
class QMenu* m_loadActionMenu = nullptr;
|
||||
class QAction* m_saveAction = nullptr;
|
||||
class QAction* m_deleteAction = nullptr;
|
||||
class QAction* m_saveAction = nullptr;
|
||||
class QAction* m_deleteAction = nullptr;
|
||||
|
||||
class QAction* m_captureAction = nullptr;
|
||||
class QAction* m_connectAction = nullptr;
|
||||
class QAction* m_eventTracingEnableAction = nullptr;
|
||||
class QAction* m_captureAction = nullptr;
|
||||
class QAction* m_connectAction = nullptr;
|
||||
class QAction* m_eventTracingEnableAction = nullptr;
|
||||
class QAction* m_eventTracingPriorityAction = nullptr;
|
||||
|
||||
uint32_t m_descriptorsNumberInFile = 0;
|
||||
uint16_t m_lastPort = 0;
|
||||
bool m_bNetworkFileRegime = false;
|
||||
bool m_bOpenedCacheFile = false;
|
||||
uint16_t m_lastPort = 0;
|
||||
bool m_bNetworkFileRegime = false;
|
||||
bool m_bOpenedCacheFile = false;
|
||||
|
||||
public:
|
||||
|
||||
@ -326,6 +347,7 @@ protected slots:
|
||||
void onEventTracingEnableChange(bool _checked);
|
||||
void onFrameTimeEditFinish();
|
||||
void onFrameTimeChanged();
|
||||
void onSnapshotClicked(bool);
|
||||
|
||||
void onBlockStatusChange(profiler::block_id_t _id, profiler::EasyBlockStatus _status);
|
||||
|
||||
@ -339,6 +361,10 @@ private:
|
||||
|
||||
// Private non-virtual methods
|
||||
|
||||
void closeProgressDialogAndClearReader();
|
||||
void onLoadingFinish(profiler::block_index_t& _nblocks);
|
||||
void onSavingFinish();
|
||||
|
||||
void configureSizes();
|
||||
|
||||
void clear();
|
||||
|
@ -7,6 +7,7 @@
|
||||
</qresource>
|
||||
<qresource prefix="/images/default">
|
||||
<file alias="binoculars">images/default/binoculars.svg</file>
|
||||
<file alias="crop">images/default/crop.svg</file>
|
||||
<file alias="exit">images/default/off.svg</file>
|
||||
<file alias="open">images/default/open-folder2.svg</file>
|
||||
<file alias="reload">images/default/reload.svg</file>
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
void printTree(TreePrinter& printer, const ::profiler::BlocksTree& tree, int level = 0, profiler::timestamp_t parent_dur = 0, profiler::timestamp_t root_dur = 0)
|
||||
void printTree(TreePrinter& printer, const profiler::BlocksTree& tree, int level = 0, profiler::timestamp_t parent_dur = 0, profiler::timestamp_t root_dur = 0)
|
||||
{
|
||||
//
|
||||
//if (tree.node){
|
||||
@ -72,7 +72,7 @@ void printTree(TreePrinter& printer, const ::profiler::BlocksTree& tree, int lev
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
::profiler::thread_blocks_tree_t threaded_trees;
|
||||
profiler::thread_blocks_tree_t threaded_trees;
|
||||
|
||||
::std::string filename;// = "test.prof";
|
||||
if (argc > 1 && argv[1])
|
||||
@ -110,14 +110,15 @@ int main(int argc, char* argv[])
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
|
||||
::profiler::SerializedData serialized_blocks, serialized_descriptors;
|
||||
::profiler::descriptors_list_t descriptors;
|
||||
::profiler::blocks_t blocks;
|
||||
::std::stringstream errorMessage;
|
||||
profiler::SerializedData serialized_blocks, serialized_descriptors;
|
||||
profiler::descriptors_list_t descriptors;
|
||||
profiler::blocks_t blocks;
|
||||
std::stringstream errorMessage;
|
||||
uint32_t descriptorsNumberInFile = 0;
|
||||
uint32_t version = 0;
|
||||
profiler::processid_t pid = 0;
|
||||
auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, blocks,
|
||||
threaded_trees, descriptorsNumberInFile, version, true, errorMessage);
|
||||
threaded_trees, descriptorsNumberInFile, version, pid, true, errorMessage);
|
||||
if (blocks_counter == 0)
|
||||
std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user