updated profiler
This commit is contained in:
parent
204f25b1f1
commit
24a27b48bd
|
@ -293,7 +293,7 @@ if (WIN_PORTABLE)
|
|||
add_definitions(-DWIN_PORTABLE)
|
||||
endif()
|
||||
|
||||
add_definitions(-DHAW_PROFILER_ENABLED)
|
||||
add_definitions(-DKORS_PROFILER_ENABLED)
|
||||
|
||||
if (MUE_ENABLE_LOAD_QML_FROM_SOURCE)
|
||||
add_definitions(-DMUE_ENABLE_LOAD_QML_FROM_SOURCE)
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
*/
|
||||
#include "profilerviewmodel.h"
|
||||
|
||||
#include "global/profiler.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
using namespace mu::diagnostics;
|
||||
using namespace haw::profiler;
|
||||
using namespace mu::profiler;
|
||||
|
||||
ProfilerViewModel::ProfilerViewModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
|
|
|
@ -23,13 +23,13 @@ set(MODULE global)
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/modularity/modularity.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/async/async.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/thirdparty/kors_logger/logger.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/thirdparty/haw_profiler/src/profiler.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/thirdparty/kors_profiler/profiler.cmake)
|
||||
|
||||
set(MODULE_SRC
|
||||
${MODULARITY_SRC}
|
||||
${ASYNC_SRC}
|
||||
${KORS_LOGGER_SRC}
|
||||
${HAW_PROFILER_SRC}
|
||||
${KORS_PROFILER_SRC}
|
||||
${CMAKE_CURRENT_LIST_DIR}/globaltypes.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/iapplication.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/iinteractive.h
|
||||
|
@ -39,6 +39,7 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/logger.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/logremover.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/logremover.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/profiler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/dataformatter.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dataformatter.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/muversion.cpp
|
||||
|
|
|
@ -24,9 +24,10 @@
|
|||
#include "modularity/ioc.h"
|
||||
#include "internal/globalconfiguration.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "logremover.h"
|
||||
#include "thirdparty/kors_logger/src/logdefdest.h"
|
||||
#include "profiler.h"
|
||||
#include "muversion.h"
|
||||
|
||||
#include "internal/application.h"
|
||||
|
@ -44,6 +45,8 @@
|
|||
|
||||
#include "diagnostics/idiagnosticspathsregister.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
using namespace mu::framework;
|
||||
using namespace mu::modularity;
|
||||
using namespace mu::io;
|
||||
|
@ -78,7 +81,7 @@ void GlobalModule::onPreInit(const IApplication::RunMode& mode)
|
|||
settings()->load();
|
||||
|
||||
//! --- Setup logger ---
|
||||
using namespace kors::logger;
|
||||
using namespace mu::logger;
|
||||
Logger* logger = Logger::instance();
|
||||
logger->clearDests();
|
||||
|
||||
|
@ -131,7 +134,7 @@ void GlobalModule::onPreInit(const IApplication::RunMode& mode)
|
|||
LOGI() << "=== Started MuseScore " << framework::MUVersion::fullVersion() << ", build number " << MUSESCORE_BUILD_NUMBER << " ===";
|
||||
|
||||
//! --- Setup profiler ---
|
||||
using namespace haw::profiler;
|
||||
using namespace mu::profiler;
|
||||
struct MyPrinter : public Profiler::Printer
|
||||
{
|
||||
void printDebug(const std::string& str) override { LOG_STREAM(Logger::DEBG, "Profiler", Color::Magenta)() << str; }
|
||||
|
@ -143,7 +146,7 @@ void GlobalModule::onPreInit(const IApplication::RunMode& mode)
|
|||
profOpt.funcsTimeEnabled = true;
|
||||
profOpt.funcsTraceEnabled = false;
|
||||
profOpt.funcsMaxThreadCount = 100;
|
||||
profOpt.dataTopCount = 150;
|
||||
profOpt.statTopCount = 150;
|
||||
|
||||
Profiler* profiler = Profiler::instance();
|
||||
profiler->setup(profOpt, new MyPrinter());
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include "thirdparty/haw_profiler/src/profiler.h"
|
||||
#include "profiler.h"
|
||||
#include "logger.h"
|
||||
|
||||
#undef FALLTHROUGH
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define MU_LOGGER_H
|
||||
|
||||
#include "thirdparty/kors_logger/src/logger.h"
|
||||
#include "thirdparty/kors_logger/src/logdefdest.h"
|
||||
#include "thirdparty/kors_logger/src/log_base.h"
|
||||
|
||||
namespace mu::logger {
|
||||
|
@ -30,6 +31,9 @@ using Logger = kors::logger::Logger;
|
|||
using Type = kors::logger::Type;
|
||||
using Level = kors::logger::Level;
|
||||
using Color = kors::logger::Color;
|
||||
using LogLayout = kors::logger::LogLayout;
|
||||
using ConsoleLogDest = kors::logger::ConsoleLogDest;
|
||||
using FileLogDest = kors::logger::FileLogDest;
|
||||
}
|
||||
|
||||
#endif // MU_LOGGER_H
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
* MuseScore-CLA-applies
|
||||
*
|
||||
* MuseScore
|
||||
* Music Composition & Notation
|
||||
*
|
||||
* Copyright (C) 2021 MuseScore BVBA and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef MU_PROFILER_H
|
||||
#define MU_PROFILER_H
|
||||
|
||||
#include "thirdparty/kors_profiler/src/profiler.h"
|
||||
|
||||
namespace mu::profiler {
|
||||
using Profiler = kors::profiler::Profiler;
|
||||
}
|
||||
|
||||
#endif // MU_PROFILER_H
|
|
@ -1,2 +0,0 @@
|
|||
*.user
|
||||
build-*
|
|
@ -1,22 +0,0 @@
|
|||
Simple profiler
|
||||
---------------
|
||||
Simple, embedded profiler with very small overhead
|
||||
(ported from https://github.com/igorkorsukov/qzebradev)
|
||||
|
||||
Features:
|
||||
* Embedded profiler (can run anywhere and anytime)
|
||||
* Function duration measure
|
||||
* Steps duration measure
|
||||
* Very small overhead
|
||||
* Enabled / disabled on compile time and run time
|
||||
* Thread safe (without use mutex)
|
||||
* Custom data printer
|
||||
|
||||
[Example](tests/main.cpp)
|
||||
|
||||
To use Profiler within your software project include the Profiler source into your project
|
||||
|
||||
Source:
|
||||
* profiler.h/cpp - profiler and macros
|
||||
|
||||
or see and include `src/profiler.cmake` in the cmake project
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
set(HAW_PROFILER_SRC
|
||||
${CMAKE_CURRENT_LIST_DIR}/profiler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/profiler.h
|
||||
)
|
||||
|
||||
set(HAW_PROFILER_INC
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4456")
|
||||
endif (MSVC)
|
|
@ -1,21 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(haw_profiler LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../src/profiler.cmake)
|
||||
|
||||
include_directories(${HAW_PROFILER_INC})
|
||||
|
||||
add_executable(haw_profiler
|
||||
main.cpp
|
||||
${HAW_PROFILER_SRC}
|
||||
)
|
||||
|
||||
target_link_libraries(haw_profiler
|
||||
pthread
|
||||
)
|
|
@ -0,0 +1,35 @@
|
|||
# profiler
|
||||
|
||||
Simple, embedded profiler with very small overhead
|
||||
Requires C++17 and higher.
|
||||
|
||||
Features:
|
||||
* Embedded profiler (can run anywhere and anytime)
|
||||
* Function duration measure
|
||||
* Steps duration measure
|
||||
* Very small overhead
|
||||
* Enabled / disabled on compile time and run time
|
||||
* Thread safe (without use mutex)
|
||||
* Custom data printer
|
||||
|
||||
[Example](example/main.cpp)
|
||||
|
||||
Used in at least two private commercial projects and one [open source](https://github.com/musescore/MuseScore).
|
||||
|
||||
## Integration
|
||||
To use Profiler within your software project include the Profiler source into your project
|
||||
|
||||
Source:
|
||||
* profiler.h/cpp - profiler and macros
|
||||
* funcinfo.h - macros for parsing signatures
|
||||
|
||||
or see and include `profiler.cmake` in the cmake project
|
||||
|
||||
## ChangeLog
|
||||
|
||||
### v1.1
|
||||
* Improved parsing of function signatures
|
||||
* Fixed get threads data
|
||||
|
||||
### v1.0
|
||||
* Ported from [https://github.com/igorkorsukov/qzebradev](https://github.com/igorkorsukov/qzebradev)
|
|
@ -0,0 +1,22 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(profiler_example LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../profiler.cmake)
|
||||
|
||||
include_directories(${KORS_PROFILER_INC})
|
||||
add_definitions(-DKORS_PROFILER_ENABLED)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
${KORS_PROFILER_SRC}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
pthread
|
||||
)
|
|
@ -72,7 +72,7 @@ public:
|
|||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::clog << "Hello World, I am Profiler\n";
|
||||
std::cout << "Hello World, I am Profiler" << std::endl;
|
||||
|
||||
Example t;
|
||||
t.example();
|
||||
|
@ -101,4 +101,25 @@ int main(int argc, char* argv[])
|
|||
Example::th_func 2.212 ms 1 2.212 ms
|
||||
|
||||
*/
|
||||
|
||||
//! NOTE Custom setup
|
||||
|
||||
// custom printer
|
||||
using namespace kors::profiler;
|
||||
struct MyPrinter : public Profiler::Printer
|
||||
{
|
||||
void printDebug(const std::string& str) override { std::clog << str << std::endl; }
|
||||
void printInfo(const std::string& str) override { std::clog << str << std::endl; }
|
||||
};
|
||||
|
||||
// options
|
||||
Profiler::Options profOpt;
|
||||
profOpt.stepTimeEnabled = true; // enable measure of steps, macros: BEGIN_STEP_TIME, STEP_TIME
|
||||
profOpt.funcsTimeEnabled = true; // enable measure of functions, macros: TRACEFUNC, TRACEFUNC_C
|
||||
profOpt.funcsTraceEnabled = false; // enable trace (output by func call), macros: TRACEFUNC, TRACEFUNC_C
|
||||
profOpt.funcsMaxThreadCount = 100; // max treads count
|
||||
profOpt.statTopCount = 150; // statistic top count
|
||||
|
||||
Profiler* profiler = Profiler::instance();
|
||||
profiler->setup(profOpt, new MyPrinter());
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
set(KORS_PROFILER_SRC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/profiler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/profiler.h
|
||||
)
|
||||
|
||||
set(KORS_PROFILER_INC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src
|
||||
)
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Igor Korsukov
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef KORS__FI_H
|
||||
#define KORS__FI_H
|
||||
|
||||
#include <string_view>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef KORS_FUNC_SIG
|
||||
#if defined(_MSC_VER)
|
||||
#define FUNC_SIG __FUNCSIG__
|
||||
#else
|
||||
#define FUNC_SIG __PRETTY_FUNCTION__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#if (__GNUC__ < 11)
|
||||
#define _KORS_NO_STRINGVIEW_CONSTEXPR_METHODS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FUNCNAME kors::funcinfo::funcNameBySig(FUNC_SIG)
|
||||
#define CLASSNAME kors::funcinfo::classNameBySig(FUNC_SIG)
|
||||
#define CLASSFUNC kors::funcinfo::classFuncBySig(FUNC_SIG)
|
||||
#define MODULENAME kors::funcinfo::moduleNameBySig(FUNC_SIG)
|
||||
|
||||
namespace kors::funcinfo {
|
||||
#ifndef _KORS_NO_STRINGVIEW_CONSTEXPR_METHODS
|
||||
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::funcName(...)
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
constexpr std::string_view funcNameBySig(const std::string_view& sig)
|
||||
{
|
||||
constexpr std::string_view Colon("::");
|
||||
constexpr std::string_view ArgBegin("(");
|
||||
constexpr std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
beginFunc = sig.find_last_of(Space, endFunc);
|
||||
}
|
||||
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
beginFunc = 0;
|
||||
} else {
|
||||
beginFunc += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginFunc, (endFunc - beginFunc));
|
||||
}
|
||||
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
constexpr std::string_view classNameBySig(const std::string_view& sig)
|
||||
{
|
||||
constexpr std::string_view Colon("::");
|
||||
constexpr std::string_view ArgBegin("(");
|
||||
constexpr std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
std::size_t beginClassColon = sig.find_last_of(Colon, beginFunc - 2);
|
||||
std::size_t beginClassSpace = sig.find_last_of(Space, beginFunc - 2);
|
||||
|
||||
std::size_t beginClass = std::string_view::npos;
|
||||
if (beginClassColon == std::string_view::npos) {
|
||||
beginClass = beginClassSpace;
|
||||
} else if (beginClassSpace == std::string_view::npos) {
|
||||
beginClass = beginClassColon;
|
||||
} else {
|
||||
beginClass = std::max(beginClassColon, beginClassSpace);
|
||||
}
|
||||
|
||||
if (beginClass == std::string_view::npos) {
|
||||
beginClass = 0;
|
||||
} else {
|
||||
beginClass += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginClass, (beginFunc - 1 - beginClass));
|
||||
}
|
||||
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
constexpr std::string_view classFuncBySig(const std::string_view& sig)
|
||||
{
|
||||
constexpr std::string_view Colon("::");
|
||||
constexpr std::string_view ArgBegin("(");
|
||||
constexpr std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return funcNameBySig(sig);
|
||||
}
|
||||
|
||||
std::size_t beginClassColon = sig.find_last_of(Colon, beginFunc - 2);
|
||||
std::size_t beginClassSpace = sig.find_last_of(Space, beginFunc - 2);
|
||||
|
||||
std::size_t beginClass = std::string_view::npos;
|
||||
if (beginClassColon == std::string_view::npos) {
|
||||
beginClass = beginClassSpace;
|
||||
} else if (beginClassSpace == std::string_view::npos) {
|
||||
beginClass = beginClassColon;
|
||||
} else {
|
||||
beginClass = std::max(beginClassColon, beginClassSpace);
|
||||
}
|
||||
|
||||
if (beginClass == std::string_view::npos) {
|
||||
beginClass = 0;
|
||||
} else {
|
||||
beginClass += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginClass, (endFunc - beginClass));
|
||||
}
|
||||
|
||||
//! NOTE Signature should be like
|
||||
//! ReturnType xxx::modulename::maybesub::ClassName::methodName()
|
||||
constexpr std::string_view moduleNameBySig(const std::string_view& sig)
|
||||
{
|
||||
constexpr std::string_view ArgBegin("(");
|
||||
constexpr std::string_view Space(" ");
|
||||
constexpr std::string_view Colon("::");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Space, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
size_t beginModule = sig.find_first_of(Colon, beginFunc) + 2;
|
||||
if (beginModule == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
size_t endModule = sig.find_first_of(Colon, beginModule);
|
||||
if (endModule == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
return sig.substr(beginModule, (endModule - beginModule));
|
||||
}
|
||||
|
||||
#else
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::funcName(...)
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
inline std::string_view funcNameBySig(const std::string_view& sig)
|
||||
{
|
||||
static const std::string_view Colon("::");
|
||||
static const std::string_view ArgBegin("(");
|
||||
static const std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
beginFunc = sig.find_last_of(Space, endFunc);
|
||||
}
|
||||
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
beginFunc = 0;
|
||||
} else {
|
||||
beginFunc += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginFunc, (endFunc - beginFunc));
|
||||
}
|
||||
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
inline std::string_view classNameBySig(const std::string_view& sig)
|
||||
{
|
||||
static const std::string_view Colon("::");
|
||||
static const std::string_view ArgBegin("(");
|
||||
static const std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
std::size_t beginClassColon = sig.find_last_of(Colon, beginFunc - 2);
|
||||
std::size_t beginClassSpace = sig.find_last_of(Space, beginFunc - 2);
|
||||
|
||||
std::size_t beginClass = std::string_view::npos;
|
||||
if (beginClassColon == std::string_view::npos) {
|
||||
beginClass = beginClassSpace;
|
||||
} else if (beginClassSpace == std::string_view::npos) {
|
||||
beginClass = beginClassColon;
|
||||
} else {
|
||||
beginClass = std::max(beginClassColon, beginClassSpace);
|
||||
}
|
||||
|
||||
if (beginClass == std::string_view::npos) {
|
||||
beginClass = 0;
|
||||
} else {
|
||||
beginClass += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginClass, (beginFunc - 1 - beginClass));
|
||||
}
|
||||
|
||||
//! NOTE Signature maybe like:
|
||||
//! * ReturnType Class::funcName(...)
|
||||
//! * ReturnType some_ns::maybesub::Class::funcName(...)
|
||||
inline std::string_view classFuncBySig(const std::string_view& sig)
|
||||
{
|
||||
static const std::string_view Colon("::");
|
||||
static const std::string_view ArgBegin("(");
|
||||
static const std::string_view Space(" ");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Colon, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return funcNameBySig(sig);
|
||||
}
|
||||
|
||||
std::size_t beginClassColon = sig.find_last_of(Colon, beginFunc - 2);
|
||||
std::size_t beginClassSpace = sig.find_last_of(Space, beginFunc - 2);
|
||||
|
||||
std::size_t beginClass = std::string_view::npos;
|
||||
if (beginClassColon == std::string_view::npos) {
|
||||
beginClass = beginClassSpace;
|
||||
} else if (beginClassSpace == std::string_view::npos) {
|
||||
beginClass = beginClassColon;
|
||||
} else {
|
||||
beginClass = std::max(beginClassColon, beginClassSpace);
|
||||
}
|
||||
|
||||
if (beginClass == std::string_view::npos) {
|
||||
beginClass = 0;
|
||||
} else {
|
||||
beginClass += 1;
|
||||
}
|
||||
|
||||
return sig.substr(beginClass, (endFunc - beginClass));
|
||||
}
|
||||
|
||||
//! NOTE Signature should be like
|
||||
//! ReturnType xxx::modulename::maybesub::ClassName::methodName()
|
||||
inline std::string_view moduleNameBySig(const std::string_view& sig)
|
||||
{
|
||||
static const std::string_view ArgBegin("(");
|
||||
static const std::string_view Space(" ");
|
||||
static const std::string_view Colon("::");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBegin);
|
||||
if (endFunc == std::string_view::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Space, endFunc);
|
||||
if (beginFunc == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
size_t beginModule = sig.find_first_of(Colon, beginFunc) + 2;
|
||||
if (beginModule == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
size_t endModule = sig.find_first_of(Colon, beginModule);
|
||||
if (endModule == std::string_view::npos) {
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
return sig.substr(beginModule, (endModule - beginModule));
|
||||
}
|
||||
|
||||
#endif // _KORS_NO_STRINGVIEW_CONSTEXPR_METHODS
|
||||
}
|
||||
|
||||
#endif // KORS__FI_H
|
|
@ -1,24 +1,41 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Igor Korsukov
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "profiler.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace haw::profiler;
|
||||
using namespace kors::profiler;
|
||||
|
||||
Profiler::Options Profiler::m_options;
|
||||
|
||||
constexpr int MAIN_THREAD_INDEX(0);
|
||||
|
||||
Profiler* Profiler::instance()
|
||||
{
|
||||
static Profiler p;
|
||||
return &p;
|
||||
}
|
||||
|
||||
Profiler::Profiler()
|
||||
{
|
||||
setup(Options(), new Printer());
|
||||
|
@ -29,6 +46,12 @@ Profiler::~Profiler()
|
|||
delete m_printer;
|
||||
}
|
||||
|
||||
Profiler* Profiler::instance()
|
||||
{
|
||||
static Profiler p;
|
||||
return &p;
|
||||
}
|
||||
|
||||
void Profiler::setup(const Options& opt, Printer* printer)
|
||||
{
|
||||
m_options = opt;
|
||||
|
@ -165,7 +188,7 @@ void Profiler::clear()
|
|||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_funcs.mutex);
|
||||
for (auto st : m_steps.timers) {
|
||||
for (auto& st : m_steps.timers) {
|
||||
delete st.second;
|
||||
}
|
||||
m_steps.timers.clear();
|
||||
|
@ -187,7 +210,7 @@ Profiler::Data Profiler::threadsData(Data::Mode mode) const
|
|||
|
||||
std::thread::id empty;
|
||||
for (size_t i = 0; i < funcsThreads.size(); ++i) {
|
||||
std::thread::id th = funcsThreads[i];
|
||||
std::thread::id th = funcsThreads.at(i);
|
||||
if (th == empty) {
|
||||
break;
|
||||
}
|
||||
|
@ -205,7 +228,7 @@ Profiler::Data Profiler::threadsData(Data::Mode mode) const
|
|||
Data::Thread thdata;
|
||||
thdata.thread = th;
|
||||
|
||||
const FuncTimers& timers = funcsTimers[i];
|
||||
const FuncTimers& timers = funcsTimers.at(i);
|
||||
for (auto it : timers) {
|
||||
const FuncTimer* ft = it.second;
|
||||
Data::Func f(
|
||||
|
@ -232,13 +255,13 @@ Profiler::Data Profiler::threadsData(Data::Mode mode) const
|
|||
std::string Profiler::threadsDataString(Data::Mode mode) const
|
||||
{
|
||||
Profiler::Data data = threadsData(mode);
|
||||
return printer()->formatData(data, mode, m_options.dataTopCount);
|
||||
return printer()->formatData(data, mode, m_options.statTopCount);
|
||||
}
|
||||
|
||||
void Profiler::printThreadsData(Data::Mode mode) const
|
||||
{
|
||||
Profiler::Data data = threadsData(mode);
|
||||
printer()->printData(data, mode, m_options.dataTopCount);
|
||||
printer()->printData(data, mode, m_options.statTopCount);
|
||||
}
|
||||
|
||||
void Profiler::print(const std::string& str)
|
||||
|
@ -266,44 +289,6 @@ bool Profiler::save_file(const std::string& path, const std::string& content)
|
|||
return count > 0;
|
||||
}
|
||||
|
||||
std::string FuncMarker::formatSig(const std::string& sig)
|
||||
{
|
||||
static const std::string Coln("::");
|
||||
static const std::string Spc(" ");
|
||||
static const std::string ArgBeg("(");
|
||||
|
||||
std::size_t endFunc = sig.find_first_of(ArgBeg);
|
||||
if (endFunc == std::string::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginFunc = sig.find_last_of(Coln, endFunc);
|
||||
if (beginFunc == std::string::npos) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
std::size_t beginClassColon = sig.find_last_of(Coln, beginFunc - 2);
|
||||
std::size_t beginClassSpace = sig.find_last_of(Spc, beginFunc - 2);
|
||||
|
||||
std::size_t beginClass = std::string::npos;
|
||||
if (beginClassColon == std::string::npos) {
|
||||
beginClass = beginClassSpace;
|
||||
} else if (beginClassSpace == std::string::npos) {
|
||||
beginClass = beginClassColon;
|
||||
} else {
|
||||
beginClass = std::max(beginClassColon, beginClassSpace);
|
||||
}
|
||||
|
||||
if (beginClass == std::string::npos) {
|
||||
beginClass = beginFunc;
|
||||
} else {
|
||||
beginClass += 1;
|
||||
}
|
||||
|
||||
std::string str = sig.substr(beginClass, (endFunc - beginClass));
|
||||
return str;
|
||||
}
|
||||
|
||||
double Profiler::StepTimer::beginMs() const
|
||||
{
|
||||
return beginTime.mlsecsElapsed();
|
||||
|
@ -373,7 +358,7 @@ using mclock = std::chrono::high_resolution_clock;
|
|||
|
||||
void Profiler::ElapsedTimer::start()
|
||||
{
|
||||
_start = mclock::now();
|
||||
m_start = mclock::now();
|
||||
}
|
||||
|
||||
void Profiler::ElapsedTimer::restart()
|
||||
|
@ -384,45 +369,42 @@ void Profiler::ElapsedTimer::restart()
|
|||
double Profiler::ElapsedTimer::mlsecsElapsed() const
|
||||
{
|
||||
auto end = mclock::now();
|
||||
std::chrono::duration<double, std::milli> elapsed = end - _start;
|
||||
std::chrono::duration<double, std::milli> elapsed = end - m_start;
|
||||
|
||||
return elapsed.count();
|
||||
}
|
||||
|
||||
void Profiler::ElapsedTimer::invalidate()
|
||||
{
|
||||
_start = mclock::time_point();
|
||||
m_start = mclock::time_point();
|
||||
}
|
||||
|
||||
bool Profiler::ElapsedTimer::isValid() const
|
||||
{
|
||||
const mclock::duration since_epoch = _start.time_since_epoch();
|
||||
const mclock::duration since_epoch = m_start.time_since_epoch();
|
||||
return since_epoch.count() > 0;
|
||||
}
|
||||
|
||||
Profiler::Printer::~Printer()
|
||||
{}
|
||||
|
||||
void Profiler::Printer::printDebug(const std::string& str)
|
||||
{
|
||||
std::cout << str << '\n';
|
||||
std::cout << str << std::endl;
|
||||
}
|
||||
|
||||
void Profiler::Printer::printInfo(const std::string& str)
|
||||
{
|
||||
std::cout << str << '\n';
|
||||
std::cout << str << std::endl;
|
||||
}
|
||||
|
||||
static std::string formatDouble(double val, size_t prec)
|
||||
std::string Profiler::Printer::formatDouble(double val, size_t prec)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(static_cast<int>(prec)) << val;
|
||||
ss << std::fixed << std::setprecision(prec) << val;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void Profiler::Printer::printStep(const std::string& tag, double beginMs, double stepMs, const std::string& info)
|
||||
{
|
||||
static const std::string COLN(" : ");
|
||||
static const std::string COLON(" : ");
|
||||
static const std::string SEP("/");
|
||||
static const std::string MS(" ms: ");
|
||||
|
||||
|
@ -431,7 +413,7 @@ void Profiler::Printer::printStep(const std::string& tag, double beginMs, double
|
|||
|
||||
str
|
||||
.append(tag)
|
||||
.append(COLN)
|
||||
.append(COLON)
|
||||
.append(formatDouble(beginMs, 3))
|
||||
.append(SEP)
|
||||
.append(formatDouble(stepMs, 3))
|
||||
|
@ -480,15 +462,17 @@ void Profiler::Printer::printData(const Data& data, Data::Mode mode, int maxcoun
|
|||
printInfo(formatData(data, mode, maxcount));
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct IsLessBySum {
|
||||
bool operator()(const Profiler::Data::Func& f, const Profiler::Data::Func& s) const
|
||||
{
|
||||
return f.sumtimeMs > s.sumtimeMs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::string Profiler::Printer::formatData(const Data& data, Data::Mode mode, int maxcount) const
|
||||
{
|
||||
struct IsLessBySum {
|
||||
bool operator()(const Profiler::Data::Func& f, const Profiler::Data::Func& s) const
|
||||
{
|
||||
return f.sumtimeMs > s.sumtimeMs;
|
||||
}
|
||||
};
|
||||
|
||||
std::stringstream stream;
|
||||
stream << "\n\n";
|
||||
|
||||
|
@ -543,27 +527,25 @@ std::string Profiler::Printer::formatData(const Data& data, Data::Mode mode, int
|
|||
return stream.str();
|
||||
}
|
||||
|
||||
std::string Profiler::Printer::leftJustified(const std::string& in, size_t width)
|
||||
{
|
||||
std::string out = in;
|
||||
if (width > out.size()) {
|
||||
out.resize(width, ' ');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#define FORMAT(str, width) leftJustified(str, width)
|
||||
#define TITLE(str) FORMAT(std::string(str), 18)
|
||||
#define VALUE(val, unit) FORMAT(std::to_string(val) + unit, 18)
|
||||
#define VALUE_D(val, unit) FORMAT(formatDouble(val, 3) + unit, 18)
|
||||
|
||||
void Profiler::Printer::funcsToStream(std::stringstream& stream,
|
||||
const std::string& title,
|
||||
const std::list<Data::Func>& funcs,
|
||||
int count) const
|
||||
{
|
||||
auto leftJustified = [](const std::string& val, size_t width) -> std::string
|
||||
{
|
||||
std::string str;
|
||||
str.resize(width, ' ');
|
||||
size_t lenght = width < val.size() ? width : val.size();
|
||||
for (size_t i = 0; i < lenght; ++i) {
|
||||
str[i] = val[i];
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
#define FORMAT(str, width) leftJustified(str, width)
|
||||
#define TITLE(str) FORMAT(std::string(str), 18)
|
||||
#define VALUE(val, unit) FORMAT(std::to_string(val) + unit, 18)
|
||||
#define VALUE_D(val, unit) FORMAT(formatDouble(val, 3) + unit, 18)
|
||||
|
||||
stream << title << "\n";
|
||||
stream << FORMAT("Function", 60) << TITLE("Call time") << TITLE("Call count") << TITLE("Sum time") << "\n";
|
||||
|
||||
|
@ -580,10 +562,5 @@ void Profiler::Printer::funcsToStream(std::stringstream& stream,
|
|||
}
|
||||
}
|
||||
|
||||
#undef FORMAT
|
||||
#undef TITLE
|
||||
#undef VALUE
|
||||
#undef VALUE_D
|
||||
|
||||
stream << "\n\n";
|
||||
}
|
|
@ -1,7 +1,31 @@
|
|||
#ifndef HAW_PROFILER_H
|
||||
#define HAW_PROFILER_H
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Igor Korsukov
|
||||
|
||||
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.
|
||||
*/
|
||||
#ifndef KORS_PROFILER_H
|
||||
#define KORS_PROFILER_H
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
@ -11,46 +35,42 @@
|
|||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef FUNC_INFO
|
||||
#if defined(_MSC_VER)
|
||||
#define FUNC_INFO __FUNCSIG__
|
||||
#else
|
||||
#define FUNC_INFO __PRETTY_FUNCTION__
|
||||
#endif
|
||||
#endif
|
||||
#include "funcinfo.h"
|
||||
|
||||
#ifdef HAW_PROFILER_ENABLED
|
||||
// #define KORS_PROFILER_ENABLED
|
||||
|
||||
#ifdef KORS_PROFILER_ENABLED
|
||||
|
||||
#ifndef TRACEFUNC
|
||||
#define TRACEFUNC \
|
||||
static std::string __func_info(haw::profiler::FuncMarker::formatSig(FUNC_INFO)); \
|
||||
haw::profiler::FuncMarker __funcMarker(__func_info);
|
||||
static std::string __func_info(CLASSFUNC); \
|
||||
kors::profiler::FuncMarker __funcMarker(__func_info);
|
||||
#endif
|
||||
|
||||
#ifndef TRACEFUNC_C
|
||||
#define TRACEFUNC_C(info) \
|
||||
static std::string __func_info(info); \
|
||||
haw::profiler::FuncMarker __funcMarkerInfo(__func_info);
|
||||
kors::profiler::FuncMarker __funcMarkerInfo(__func_info);
|
||||
#endif
|
||||
|
||||
#ifndef BEGIN_STEP_TIME
|
||||
#define BEGIN_STEP_TIME(tag) \
|
||||
if (haw::profiler::Profiler::options().stepTimeEnabled) \
|
||||
{ haw::profiler::Profiler::instance()->stepTime(tag, std::string("Begin"), true); }
|
||||
if (kors::profiler::Profiler::options().stepTimeEnabled) \
|
||||
{ kors::profiler::Profiler::instance()->stepTime(tag, std::string("Begin"), true); }
|
||||
#endif
|
||||
|
||||
#ifndef STEP_TIME
|
||||
#define STEP_TIME(tag, info) \
|
||||
if (haw::profiler::Profiler::options().stepTimeEnabled) \
|
||||
{ haw::profiler::Profiler::instance()->stepTime(tag, info); }
|
||||
if (kors::profiler::Profiler::options().stepTimeEnabled) \
|
||||
{ kors::profiler::Profiler::instance()->stepTime(tag, info); }
|
||||
#endif
|
||||
|
||||
#ifndef PROFILER_CLEAR
|
||||
#define PROFILER_CLEAR haw::profiler::Profiler::instance()->clear();
|
||||
#define PROFILER_CLEAR kors::profiler::Profiler::instance()->clear();
|
||||
#endif
|
||||
|
||||
#ifndef PROFILER_PRINT
|
||||
#define PROFILER_PRINT haw::profiler::Profiler::instance()->printThreadsData();
|
||||
#define PROFILER_PRINT kors::profiler::Profiler::instance()->printThreadsData();
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -64,7 +84,7 @@
|
|||
|
||||
#endif
|
||||
|
||||
namespace haw::profiler {
|
||||
namespace kors::profiler {
|
||||
class Profiler
|
||||
{
|
||||
public:
|
||||
|
@ -72,12 +92,12 @@ public:
|
|||
static Profiler* instance();
|
||||
|
||||
struct Options {
|
||||
bool stepTimeEnabled{ true };
|
||||
bool funcsTimeEnabled{ true };
|
||||
bool funcsTraceEnabled{ false };
|
||||
size_t funcsMaxThreadCount{ 100 };
|
||||
int dataTopCount{ 150 };
|
||||
Options() {}
|
||||
bool stepTimeEnabled = true;
|
||||
bool funcsTimeEnabled = true;
|
||||
bool funcsTraceEnabled = false;
|
||||
size_t funcsMaxThreadCount = 100;
|
||||
int statTopCount = 150;
|
||||
};
|
||||
|
||||
struct Data {
|
||||
|
@ -89,8 +109,8 @@ public:
|
|||
|
||||
struct Func {
|
||||
std::string func;
|
||||
long callcount{ 0 };
|
||||
double sumtimeMs{ 0. };
|
||||
long callcount = 0;
|
||||
double sumtimeMs = 0.0;
|
||||
Func() {}
|
||||
Func(const std::string& f, long cc, double st)
|
||||
: func(f), callcount(cc), sumtimeMs(st) {}
|
||||
|
@ -106,7 +126,7 @@ public:
|
|||
};
|
||||
|
||||
struct Printer {
|
||||
virtual ~Printer();
|
||||
virtual ~Printer() = default;
|
||||
virtual void printDebug(const std::string& str);
|
||||
virtual void printInfo(const std::string& str);
|
||||
virtual void printStep(const std::string& tag, double beginMs, double stepMs, const std::string& info);
|
||||
|
@ -116,6 +136,9 @@ public:
|
|||
virtual std::string formatData(const Data& data, Data::Mode mode, int maxcount) const;
|
||||
virtual void funcsToStream(std::stringstream& stream, const std::string& title, const std::list<Data::Func>& funcs,
|
||||
int count) const;
|
||||
|
||||
static std::string formatDouble(double val, size_t prec);
|
||||
static std::string leftJustified(const std::string& in, size_t width);
|
||||
};
|
||||
|
||||
struct ElapsedTimer {
|
||||
|
@ -126,14 +149,14 @@ public:
|
|||
bool isValid() const;
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point _start;
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
};
|
||||
|
||||
struct FuncTimer {
|
||||
const std::string& func;
|
||||
ElapsedTimer timer;
|
||||
long callcount;
|
||||
double sumtimeMs;
|
||||
long callcount = 0;
|
||||
double sumtimeMs = 0.0;
|
||||
explicit FuncTimer(const std::string& f)
|
||||
: func(f), callcount(0), sumtimeMs(0) {}
|
||||
};
|
||||
|
@ -199,12 +222,12 @@ private:
|
|||
|
||||
bool save_file(const std::string& path, const std::string& content);
|
||||
|
||||
Printer* m_printer{ nullptr };
|
||||
Printer* m_printer = nullptr;
|
||||
|
||||
StepsData m_steps;
|
||||
mutable FuncsData m_funcs;
|
||||
|
||||
size_t m_stackCounter{ 0 };
|
||||
size_t m_stackCounter = 0;
|
||||
};
|
||||
|
||||
struct FuncMarker
|
||||
|
@ -224,11 +247,9 @@ struct FuncMarker
|
|||
}
|
||||
}
|
||||
|
||||
static std::string formatSig(const std::string& sig);
|
||||
|
||||
Profiler::FuncTimer* timer{ nullptr };
|
||||
Profiler::FuncTimer* timer = nullptr;
|
||||
const std::string& func;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // XTZ_PROFILER_H
|
||||
#endif // KORS_PROFILER_H
|
Loading…
Reference in New Issue