mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-28 05:06:40 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_ARBITRARY_VALUE_H
|
||||
#define EASY_PROFILER_ARBITRARY_VALUE_H
|
||||
|
||||
#include <easy/details/arbitrary_value_public_types.h>
|
||||
|
||||
//
|
||||
// USING_EASY_PROFILER is defined in details/profiler_in_use.h
|
||||
// if defined BUILD_WITH_EASY_PROFILER and not defined DISABLE_EASY_PROFILER
|
||||
//
|
||||
|
||||
//
|
||||
// BUILD_WITH_EASY_PROFILER is defined in CMakeLists.txt if your project is linked to easy_profiler.
|
||||
//
|
||||
|
||||
//
|
||||
// DISABLE_EASY_PROFILER may be defined manually in source-file before #include <easy/profiler.h>
|
||||
// to disable profiler for certain source-file or project.
|
||||
//
|
||||
|
||||
#ifdef USING_EASY_PROFILER
|
||||
|
||||
/** Macro used to create a unique Value Identification Number.
|
||||
|
||||
Use this if you want to change the same value from different places in your code.
|
||||
Otherwise do not mind.
|
||||
|
||||
\code
|
||||
struct A {
|
||||
int someCount;
|
||||
};
|
||||
|
||||
void foo(const A& a) {
|
||||
EASY_VALUE("foo count", a.someCount); // Value ID is automatically set to (uint64_t)&a.someCount
|
||||
|
||||
// This notation is completely the same as EASY_VALUE("foo count", a.someCount, EASY_VIN(a.someCount));
|
||||
}
|
||||
|
||||
void bar(const A& b) {
|
||||
EASY_VALUE("bar count", b.someCount); // Same ID as for "foo count" if &b == &a (and different ID otherwise)
|
||||
}
|
||||
|
||||
void baz(const A& c) {
|
||||
EASY_VALUE("baz count", c.someCount, EASY_VIN(EASY_FUNC_NAME)); // Different ID from "foo count" and "bar count"
|
||||
EASY_VALUE("qux count", 100500, EASY_VIN(EASY_FUNC_NAME)); // Same ID as for "baz count"
|
||||
}
|
||||
\endcode
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_VIN(member) ::profiler::ValueId(member)
|
||||
|
||||
/** Macro used to identify global value which would be recognized by it's name in GUI.
|
||||
|
||||
\code
|
||||
struct A {
|
||||
int someCount;
|
||||
};
|
||||
|
||||
struct B {
|
||||
int someOtherCount;
|
||||
};
|
||||
|
||||
void foo(const A& a) {
|
||||
EASY_VALUE("Count", a.someCount, EASY_GLOBAL_VIN);
|
||||
}
|
||||
|
||||
void bar(const B& b) {
|
||||
EASY_VALUE("Count", b.someOtherCount, EASY_GLOBAL_VIN); // Same ID as for foo::"Count" despite of &b != &a
|
||||
}
|
||||
\endcode
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_GLOBAL_VIN ::profiler::ValueId()
|
||||
|
||||
/** Macro used to identify unique value.
|
||||
|
||||
\code
|
||||
struct A {
|
||||
int someCount;
|
||||
};
|
||||
|
||||
void foo(const A& a) {
|
||||
// All these values would have different IDs despite of names, pointers and values are the same
|
||||
EASY_VALUE("foo count", a.someCount, EASY_UNIQUE_VIN);
|
||||
EASY_VALUE("foo count", a.someCount, EASY_UNIQUE_VIN);
|
||||
EASY_VALUE("foo count", a.someCount, EASY_UNIQUE_VIN);
|
||||
}
|
||||
\endcode
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_UNIQUE_VIN ::profiler::ValueId(EASY_UNIQUE_DESC(__LINE__))
|
||||
|
||||
/** Macro used to store single arbitrary value.
|
||||
|
||||
\note Also stores a time-stamp of it's occurrence like an Event.
|
||||
|
||||
\note To store a dynamic array (which size is unknown at compile time), please, use EASY_ARRAY macro.
|
||||
|
||||
\note Currently arbitrary values support only compile-time names.
|
||||
|
||||
\sa EASY_ARRAY, EASY_TEXT, EASY_STRING
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_VALUE(name, value, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BlockType::Value, ::profiler::extract_color(__VA_ARGS__), false));\
|
||||
::profiler::setValue(EASY_UNIQUE_DESC(__LINE__), value, ::profiler::extract_value_id(value, ## __VA_ARGS__));
|
||||
|
||||
/** Macro used to store an array of arbitrary values.
|
||||
|
||||
\note Also stores a time-stamp of it's occurrence like an Event.
|
||||
|
||||
\note Currently arbitrary values support only compile-time names.
|
||||
|
||||
\warning Max data size (sizeof(value) * size) is MAX_BLOCK_DATA_SIZE. Passing bigger size has undefined behavior.
|
||||
|
||||
\sa EASY_VALUE, EASY_TEXT, EASY_STRING, MAX_BLOCK_DATA_SIZE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_ARRAY(name, value, size, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BlockType::Value, ::profiler::extract_color(__VA_ARGS__), false));\
|
||||
::profiler::setValue(EASY_UNIQUE_DESC(__LINE__), value, ::profiler::extract_value_id(value, ## __VA_ARGS__), size);
|
||||
|
||||
/** Macro used to store custom text.
|
||||
|
||||
Could be C-string or std::string.
|
||||
|
||||
\note Also stores a time-stamp of it's occurrence like an Event.
|
||||
|
||||
\note Currently arbitrary values support only compile-time names.
|
||||
|
||||
\warning Max string length is MAX_BLOCK_DATA_SIZE (including trailing '\0'). Passing bigger size has undefined behavior.
|
||||
|
||||
\sa EASY_VALUE, EASY_ARRAY, EASY_STRING, MAX_BLOCK_DATA_SIZE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_TEXT(name, text, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BlockType::Value, ::profiler::extract_color(__VA_ARGS__), false));\
|
||||
::profiler::setText(EASY_UNIQUE_DESC(__LINE__), text, ::profiler::extract_value_id(text , ## __VA_ARGS__));
|
||||
|
||||
/** Macro used to store custom text of specified length.
|
||||
|
||||
Same as EASY_TEXT, but with explicitly specified length.
|
||||
Use this for C-strings of known length (compile-time or run-time).
|
||||
|
||||
\note Recommendation (not a requirement): Take into account a zero-terminator '\0' symbol (e.g. strlen("BlaBla") + 1).
|
||||
|
||||
\note Also stores a time-stamp of it's occurrence like an Event.
|
||||
|
||||
\note Currently arbitrary values support only compile-time names.
|
||||
|
||||
\warning Max string length is MAX_BLOCK_DATA_SIZE (including trailing '\0'). Passing bigger size has undefined behavior.
|
||||
|
||||
\sa EASY_VALUE, EASY_ARRAY, EASY_TEXT, MAX_BLOCK_DATA_SIZE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_STRING(name, text, size, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BlockType::Value, ::profiler::extract_color(__VA_ARGS__), false));\
|
||||
::profiler::setText(EASY_UNIQUE_DESC(__LINE__), text, ::profiler::extract_value_id(text, ## __VA_ARGS__), size);
|
||||
|
||||
namespace profiler
|
||||
{
|
||||
|
||||
extern "C" PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data,
|
||||
uint16_t _size, bool _isArray, ValueId _vin);
|
||||
|
||||
template <class T>
|
||||
inline void setValue(const BaseBlockDescriptor* _desc, T _value, ValueId _vin)
|
||||
{
|
||||
static_assert(!::std::is_pointer<T>::value,
|
||||
"You should not pass pointers into EASY_VALUE. Pass a reference instead.");
|
||||
|
||||
using Type = typename ::std::remove_reference<typename ::std::remove_cv<T>::type>::type;
|
||||
|
||||
static_assert(StdToDataType<Type>::data_type != DataType::TypesCount,
|
||||
"You should use standard builtin scalar types as profiler::Value type!");
|
||||
|
||||
storeValue(_desc, StdToDataType<Type>::data_type, &_value, static_cast<uint16_t>(sizeof(Type)), false, _vin);
|
||||
}
|
||||
|
||||
///< WARNING: Passing _arraySize > (MAX_BLOCK_DATA_SIZE / sizeof(T)) may cause undefined behavior!
|
||||
template <class T>
|
||||
inline void setValue(const BaseBlockDescriptor* _desc, const T* _valueArray, ValueId _vin, uint16_t _arraySize)
|
||||
{
|
||||
static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
|
||||
"You should use standard builtin scalar types as profiler::Value type!");
|
||||
|
||||
storeValue(_desc, StdToDataType<T>::data_type, _valueArray, static_cast<uint16_t>(sizeof(T) * _arraySize), true, _vin);
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
inline void setValue(const BaseBlockDescriptor* _desc, const T (&_value)[N], ValueId _vin)
|
||||
{
|
||||
static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
|
||||
"You should use standard builtin scalar types as profiler::Value type!");
|
||||
|
||||
static_assert(sizeof(_value) <= MAX_BLOCK_DATA_SIZE, "Maximum arbitrary values data size exceeded.");
|
||||
|
||||
storeValue(_desc, StdToDataType<T>::data_type, _value, static_cast<uint16_t>(sizeof(_value)), true, _vin);
|
||||
}
|
||||
|
||||
///< WARNING: Passing _textLength > MAX_BLOCK_DATA_SIZE may cause undefined behavior!
|
||||
inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin, uint16_t _textLength)
|
||||
{
|
||||
storeValue(_desc, DataType::String, _text, _textLength, true, _vin);
|
||||
}
|
||||
|
||||
///< WARNING: Passing _text with length > MAX_BLOCK_DATA_SIZE may cause undefined behavior!
|
||||
inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin)
|
||||
{
|
||||
storeValue(_desc, DataType::String, _text, static_cast<uint16_t>(strlen(_text) + 1), true, _vin);
|
||||
}
|
||||
|
||||
///< WARNING: Passing _text with length > MAX_BLOCK_DATA_SIZE may cause undefined behavior!
|
||||
inline void setText(const BaseBlockDescriptor* _desc, const ::std::string& _text, ValueId _vin)
|
||||
{
|
||||
storeValue(_desc, DataType::String, _text.c_str(), static_cast<uint16_t>(_text.size() + 1), true, _vin);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
inline void setText(const BaseBlockDescriptor* _desc, const char (&_text)[N], ValueId _vin)
|
||||
{
|
||||
static_assert(N <= MAX_BLOCK_DATA_SIZE, "Maximum arbitrary values data size exceeded.");
|
||||
storeValue(_desc, DataType::String, &_text[0], static_cast<uint16_t>(N), true, _vin);
|
||||
}
|
||||
|
||||
} // end of namespace profiler.
|
||||
|
||||
#else
|
||||
|
||||
# if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
# endif
|
||||
|
||||
# define EASY_GLOBAL_VIN
|
||||
# define EASY_UNIQUE_VIN
|
||||
# define EASY_VIN(member)
|
||||
# define EASY_VALUE(...)
|
||||
# define EASY_ARRAY(...)
|
||||
# define EASY_TEXT(...)
|
||||
# define EASY_STRING(...)
|
||||
|
||||
namespace profiler
|
||||
{
|
||||
|
||||
inline void storeValue(const BaseBlockDescriptor*, DataType, const void*, uint16_t, bool, ValueId) {}
|
||||
|
||||
template <class T>
|
||||
inline void setValue(const BaseBlockDescriptor*, T, ValueId) {}
|
||||
|
||||
template <class T>
|
||||
inline void setValue(const BaseBlockDescriptor*, const T*, ValueId, uint16_t) {}
|
||||
|
||||
template <class T, size_t N>
|
||||
inline void setValue(const BaseBlockDescriptor*, const T (&)[N], ValueId) {}
|
||||
|
||||
inline void setText(const BaseBlockDescriptor*, const char*, ValueId, uint16_t) {}
|
||||
|
||||
inline void setText(const BaseBlockDescriptor*, const char*, ValueId) {}
|
||||
|
||||
inline void setText(const BaseBlockDescriptor*, const ::std::string&, ValueId) {}
|
||||
|
||||
template <size_t N>
|
||||
inline void setText(const BaseBlockDescriptor*, const char (&)[N], ValueId) {}
|
||||
|
||||
} // end of namespace profiler.
|
||||
|
||||
# if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
|
||||
#endif // USING_EASY_PROFILER
|
||||
|
||||
#endif // EASY_PROFILER_ARBITRARY_VALUE_H
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_ARBITRARY_VALUE_AUX_H
|
||||
#define EASY_PROFILER_ARBITRARY_VALUE_AUX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
|
||||
struct ThreadStorage;
|
||||
|
||||
namespace profiler
|
||||
{
|
||||
|
||||
using vin_t = uint64_t;
|
||||
|
||||
class ValueId EASY_FINAL
|
||||
{
|
||||
friend ::ThreadStorage;
|
||||
const void* m_id;
|
||||
|
||||
public:
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
inline EASY_CONSTEXPR_FCN ValueId(const ValueId& _another) : m_id(_another.m_id) {}
|
||||
inline EASY_CONSTEXPR_FCN ValueId(ValueId&& _another) : m_id(_another.m_id) {}
|
||||
#else
|
||||
inline EASY_CONSTEXPR_FCN ValueId(const ValueId&) = default;
|
||||
inline EASY_CONSTEXPR_FCN ValueId(ValueId&&) = default;
|
||||
#endif
|
||||
|
||||
explicit inline EASY_CONSTEXPR_FCN ValueId() : m_id(nullptr) {}
|
||||
explicit inline EASY_CONSTEXPR_FCN ValueId(const void* _member) : m_id(_member) {}
|
||||
|
||||
template <class T>
|
||||
explicit inline EASY_CONSTEXPR_FCN ValueId(const T& _member) : m_id(&_member) {}
|
||||
|
||||
template <class T, size_t N>
|
||||
explicit inline EASY_CONSTEXPR_FCN ValueId(const T (&_member)[N]) : m_id(_member) {}
|
||||
|
||||
ValueId& operator = (const ValueId&) = delete;
|
||||
ValueId& operator = (ValueId&&) = delete;
|
||||
};
|
||||
|
||||
namespace {
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN bool subextract_value_id(TArgs...);
|
||||
|
||||
template <>
|
||||
inline EASY_CONSTEXPR_FCN bool subextract_value_id<>() { return false; }
|
||||
|
||||
template <class T>
|
||||
inline EASY_CONSTEXPR_FCN bool subextract_value_id(T) { return false; }
|
||||
|
||||
inline EASY_CONSTEXPR_FCN ValueId subextract_value_id(ValueId _value) { return _value; }
|
||||
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN ValueId subextract_value_id(ValueId _value, TArgs...) { return _value; }
|
||||
|
||||
template <class T, class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN auto subextract_value_id(T, TArgs... _args) -> decltype(subextract_value_id(_args...)) {
|
||||
return subextract_value_id(_args...);
|
||||
}
|
||||
|
||||
struct GetFirst {
|
||||
template <class T, class ... TArgs>
|
||||
static EASY_CONSTEXPR_FCN ValueId get(const T& _first, TArgs...) { return ValueId(_first); }
|
||||
|
||||
template <class T, size_t N, class ... TArgs>
|
||||
static EASY_CONSTEXPR_FCN ValueId get(const T (&_first)[N], TArgs...) { return ValueId(_first); }
|
||||
};
|
||||
|
||||
struct GetRest {
|
||||
template <class T, class ... TArgs>
|
||||
static EASY_CONSTEXPR_FCN ValueId get(const T&, TArgs... _args) { return subextract_value_id(_args...); }
|
||||
};
|
||||
} // end of noname namespace.
|
||||
|
||||
template <class T, class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN ValueId extract_value_id(const T& _first, TArgs... _args) {
|
||||
return ::std::conditional<::std::is_same<ValueId, decltype(subextract_value_id(_args...))>::value, GetRest, GetFirst>
|
||||
::type::get(_first, _args...);
|
||||
}
|
||||
|
||||
template <class T, size_t N, class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN ValueId extract_value_id(const T (&_first)[N], TArgs... _args) {
|
||||
return ::std::conditional<::std::is_same<ValueId, decltype(subextract_value_id(_args...))>::value, GetRest, GetFirst>
|
||||
::type::get(_first, _args...);
|
||||
}
|
||||
|
||||
} // end of namespace profiler.
|
||||
|
||||
#endif // EASY_PROFILER_ARBITRARY_VALUE_AUX_H
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_ARBITRARY_VALUE_PUBLIC_TYPES_H
|
||||
#define EASY_PROFILER_ARBITRARY_VALUE_PUBLIC_TYPES_H
|
||||
|
||||
#include <easy/details/arbitrary_value_aux.h>
|
||||
#include <easy/details/profiler_public_types.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
namespace profiler
|
||||
{
|
||||
|
||||
enum class DataType : uint8_t
|
||||
{
|
||||
Bool = 0,
|
||||
Char,
|
||||
Int8,
|
||||
Uint8,
|
||||
Int16,
|
||||
Uint16,
|
||||
Int32,
|
||||
Uint32,
|
||||
Int64,
|
||||
Uint64,
|
||||
Float,
|
||||
Double,
|
||||
String,
|
||||
|
||||
TypesCount
|
||||
}; // end of enum class DataType.
|
||||
|
||||
template <DataType dataType> struct StdType;
|
||||
|
||||
template <class T> struct StdToDataType EASY_FINAL {
|
||||
EASY_STATIC_CONSTEXPR auto data_type = DataType::TypesCount;
|
||||
};
|
||||
|
||||
# define EASY_DATATYPE_CONVERSION(DataTypeName, StdTypeName)\
|
||||
template <> struct StdType<DataTypeName> EASY_FINAL { using value_type = StdTypeName; };\
|
||||
template <> struct StdToDataType<StdTypeName> EASY_FINAL { EASY_STATIC_CONSTEXPR auto data_type = DataTypeName; }
|
||||
|
||||
EASY_DATATYPE_CONVERSION(DataType::Bool , bool );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Char , char );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Int8 , int8_t );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Uint8 , uint8_t );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Int16 , int16_t );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Uint16, uint16_t);
|
||||
EASY_DATATYPE_CONVERSION(DataType::Int32 , int32_t );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Uint32, uint32_t);
|
||||
EASY_DATATYPE_CONVERSION(DataType::Int64 , int64_t );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Uint64, uint64_t);
|
||||
EASY_DATATYPE_CONVERSION(DataType::Float , float );
|
||||
EASY_DATATYPE_CONVERSION(DataType::Double, double );
|
||||
|
||||
# undef EASY_DATATYPE_CONVERSION
|
||||
|
||||
template <> struct StdType<DataType::String> EASY_FINAL { using value_type = char; };
|
||||
template <> struct StdToDataType<const char*> EASY_FINAL { EASY_STATIC_CONSTEXPR auto data_type = DataType::String; };
|
||||
|
||||
} // end of namespace profiler.
|
||||
|
||||
#endif //EASY_PROFILER_ARBITRARY_VALUE_PUBLIC_TYPES_H
|
||||
@@ -0,0 +1,254 @@
|
||||
/************************************************************************
|
||||
* file name : easy_compiler_support.h
|
||||
* ----------------- :
|
||||
* creation time : 2016/09/22
|
||||
* authors : Victor Zarubkin, Sergey Yagovtsev
|
||||
* emails : v.s.zarubkin@gmail.com, yse.sey@gmail.com
|
||||
* ----------------- :
|
||||
* description : This file contains auxiliary profiler macros for different compiler support.
|
||||
* ----------------- :
|
||||
* license : Lightweight profiler library for c++
|
||||
* : Copyright(C) 2016-2019 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_COMPILER_SUPPORT_H
|
||||
#define EASY_PROFILER_COMPILER_SUPPORT_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(_WIN32) && !defined(EASY_PROFILER_STATIC)
|
||||
// Visual Studio and MinGW
|
||||
# ifdef _BUILD_PROFILER
|
||||
# define PROFILER_API __declspec(dllexport)
|
||||
# else
|
||||
# define PROFILER_API __declspec(dllimport)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# if __cplusplus >= 201703L
|
||||
# define EASY_STD 17
|
||||
# elif __cplusplus >= 201402L
|
||||
# define EASY_STD 14
|
||||
# else
|
||||
# define EASY_STD 11
|
||||
# endif
|
||||
#else
|
||||
# define EASY_STD 11
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Visual Studio
|
||||
|
||||
# if defined(EASY_OPTION_PRETTY_PRINT_FUNCTIONS) && EASY_OPTION_PRETTY_PRINT_FUNCTIONS != 0
|
||||
# define EASY_FUNC_NAME __FUNCSIG__
|
||||
# else
|
||||
# define EASY_FUNC_NAME __FUNCTION__
|
||||
# endif
|
||||
|
||||
# if _MSC_VER <= 1800
|
||||
// There is no support for C++11 thread_local keyword prior to Visual Studio 2015. Use __declspec(thread) instead.
|
||||
// There is also no support for C++11 magic statics feature :( So it becomes slightly harder to initialize static vars - additional "if" for each profiler block.
|
||||
# define EASY_THREAD_LOCAL __declspec(thread)
|
||||
# define EASY_LOCAL_STATIC_PTR(VarType, VarName, VarInitializer)\
|
||||
__declspec(thread) static VarType VarName = 0;\
|
||||
if (!VarName)\
|
||||
VarName = VarInitializer
|
||||
|
||||
// No constexpr support before Visual Studio 2015
|
||||
# define EASY_CONSTEXPR const
|
||||
# define EASY_STATIC_CONSTEXPR static const
|
||||
# define EASY_CONSTEXPR_FCN
|
||||
|
||||
// No noexcept support before Visual Studio 2015
|
||||
# define EASY_NOEXCEPT throw()
|
||||
|
||||
// No alignof support before Visual Studio 2015
|
||||
# define EASY_ALIGNOF(x) __alignof(x)
|
||||
# endif
|
||||
|
||||
# if EASY_STD > 11 && _MSC_VER >= 1900
|
||||
# define EASY_LAMBDA_MOVE_CAPTURE
|
||||
# endif
|
||||
|
||||
# define EASY_FORCE_INLINE __forceinline
|
||||
|
||||
#elif defined(__clang__)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Clang Compiler
|
||||
|
||||
# define EASY_COMPILER_VERSION (__clang_major__ * 10 + __clang_minor__)
|
||||
|
||||
# if EASY_COMPILER_VERSION < 33 || (defined(__APPLE_CC__) && __APPLE_CC__ < 8000)
|
||||
// There is no support for C++11 thread_local keyword prior to Clang v3.3 and Apple LLVM clang 8.0. Use __thread instead.
|
||||
# define EASY_THREAD_LOCAL __thread
|
||||
# endif
|
||||
|
||||
# if EASY_COMPILER_VERSION < 31
|
||||
// No constexpr support before Clang v3.1
|
||||
# define EASY_CONSTEXPR const
|
||||
# define EASY_STATIC_CONSTEXPR static const
|
||||
# define EASY_CONSTEXPR_FCN
|
||||
# endif
|
||||
|
||||
# if EASY_COMPILER_VERSION < 29
|
||||
// There is no support for C++11 magic statics feature prior to clang 2.9. It becomes slightly harder to initialize static vars - additional "if" for each profiler block.
|
||||
# define EASY_LOCAL_STATIC_PTR(VarType, VarName, VarInitializer)\
|
||||
EASY_THREAD_LOCAL static VarType VarName = 0;\
|
||||
if (!VarName)\
|
||||
VarName = VarInitializer
|
||||
|
||||
// There is no support for C++11 final keyword prior to Clang v2.9
|
||||
# define EASY_FINAL
|
||||
# endif
|
||||
|
||||
# if EASY_STD > 11 && EASY_COMPILER_VERSION >= 34
|
||||
# define EASY_LAMBDA_MOVE_CAPTURE
|
||||
# endif
|
||||
|
||||
# define EASY_FORCE_INLINE inline __attribute__((always_inline))
|
||||
# undef EASY_COMPILER_VERSION
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GNU Compiler
|
||||
|
||||
# define EASY_COMPILER_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)
|
||||
|
||||
# if EASY_COMPILER_VERSION < 48
|
||||
// There is no support for C++11 thread_local keyword prior to gcc 4.8. Use __thread instead.
|
||||
# define EASY_THREAD_LOCAL __thread
|
||||
# endif
|
||||
|
||||
# if EASY_COMPILER_VERSION < 46
|
||||
// No constexpr support before GCC v4.6
|
||||
# define EASY_CONSTEXPR const
|
||||
# define EASY_STATIC_CONSTEXPR static const
|
||||
# define EASY_CONSTEXPR_FCN
|
||||
|
||||
// No noexcept support before GCC v4.6
|
||||
# define EASY_NOEXCEPT throw()
|
||||
# endif
|
||||
|
||||
# if EASY_COMPILER_VERSION < 43
|
||||
// There is no support for C++11 magic statics feature prior to gcc 4.3. It becomes slightly harder to initialize static vars - additional "if" for each profiler block.
|
||||
# define EASY_LOCAL_STATIC_PTR(VarType, VarName, VarInitializer)\
|
||||
EASY_THREAD_LOCAL static VarType VarName = 0;\
|
||||
if (!VarName)\
|
||||
VarName = VarInitializer
|
||||
# endif
|
||||
|
||||
# if EASY_COMPILER_VERSION < 47
|
||||
// There is no support for C++11 final keyword prior to gcc 4.7
|
||||
# define EASY_FINAL
|
||||
# endif
|
||||
|
||||
# if EASY_STD > 11 && EASY_COMPILER_VERSION >= 49
|
||||
# define EASY_LAMBDA_MOVE_CAPTURE
|
||||
# endif
|
||||
|
||||
# define EASY_FORCE_INLINE inline __attribute__((always_inline))
|
||||
# undef EASY_COMPILER_VERSION
|
||||
|
||||
#else
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TODO: Add other compilers support
|
||||
|
||||
static_assert(false, "EasyProfiler is not configured for using your compiler type. Please, contact developers.");
|
||||
#endif
|
||||
// END
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Default values
|
||||
|
||||
#ifndef EASY_FUNC_NAME
|
||||
# if defined(EASY_OPTION_PRETTY_PRINT_FUNCTIONS) && EASY_OPTION_PRETTY_PRINT_FUNCTIONS != 0
|
||||
# define EASY_FUNC_NAME __PRETTY_FUNCTION__
|
||||
# else
|
||||
# define EASY_FUNC_NAME __func__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EASY_THREAD_LOCAL
|
||||
# define EASY_THREAD_LOCAL thread_local
|
||||
# define EASY_CXX11_TLS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifndef EASY_LOCAL_STATIC_PTR
|
||||
# define EASY_LOCAL_STATIC_PTR(VarType, VarName, VarInitializer) static VarType VarName = VarInitializer
|
||||
# define EASY_MAGIC_STATIC_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifndef EASY_FINAL
|
||||
# define EASY_FINAL final
|
||||
#endif
|
||||
|
||||
#ifndef EASY_FORCE_INLINE
|
||||
# define EASY_FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
#ifndef EASY_CONSTEXPR
|
||||
# define EASY_CONSTEXPR constexpr
|
||||
# define EASY_STATIC_CONSTEXPR static constexpr
|
||||
# define EASY_CONSTEXPR_FCN constexpr
|
||||
# define EASY_CONSTEXPR_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifndef EASY_NOEXCEPT
|
||||
# define EASY_NOEXCEPT noexcept
|
||||
# define EASY_NOEXCEPT_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifndef EASY_ALIGNOF
|
||||
# define EASY_ALIGNOF(x) alignof(x)
|
||||
#endif
|
||||
|
||||
#ifndef PROFILER_API
|
||||
# define PROFILER_API
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EASY_PROFILER_COMPILER_SUPPORT_H
|
||||
@@ -0,0 +1,218 @@
|
||||
/************************************************************************
|
||||
* file name : profiler_aux.h
|
||||
* ----------------- :
|
||||
* creation time : 2016/06/11
|
||||
* author : Victor Zarubkin
|
||||
* email : v.s.zarubkin@gmail.com
|
||||
* ----------------- :
|
||||
* description : This file contains auxiliary profiler macros and funcitons.
|
||||
* ----------------- :
|
||||
* change log : * 2016/06/11 Victor Zarubkin: Moved sources from profiler.h
|
||||
* :
|
||||
* : *
|
||||
* ----------------- :
|
||||
* license : Lightweight profiler library for c++
|
||||
* : Copyright(C) 2016-2019 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_AUX_H
|
||||
#define EASY_PROFILER_AUX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
#include <easy/details/profiler_colors.h>
|
||||
#include <easy/details/profiler_in_use.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace profiler {
|
||||
|
||||
enum EasyBlockStatus : uint8_t {
|
||||
OFF = 0, ///< The block is OFF
|
||||
ON = 1, ///< The block is ON (but if it's parent block is off recursively then this block will be off too)
|
||||
FORCE_ON = ON | 2, ///< The block is ALWAYS ON (even if it's parent has turned off all children)
|
||||
OFF_RECURSIVE = 4, ///< The block is OFF and all of it's children by call-stack are also OFF.
|
||||
ON_WITHOUT_CHILDREN = ON | OFF_RECURSIVE, ///< The block is ON but all of it's children are OFF.
|
||||
FORCE_ON_WITHOUT_CHILDREN = FORCE_ON | OFF_RECURSIVE, ///< The block is ALWAYS ON but all of it's children are OFF.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
# define EASY_STRINGIFY(a) #a
|
||||
# define EASY_STRINGIFICATION(a) EASY_STRINGIFY(a)
|
||||
# define EASY_TOKEN_JOIN(x, y) x ## y
|
||||
# define EASY_TOKEN_CONCATENATE(x, y) EASY_TOKEN_JOIN(x, y)
|
||||
# define EASY_UNIQUE_BLOCK(x) EASY_TOKEN_CONCATENATE(unique_profiler_mark_name_, x)
|
||||
# define EASY_UNIQUE_FRAME_COUNTER(x) EASY_TOKEN_CONCATENATE(unique_profiler_frame_mark_name_, x)
|
||||
# define EASY_UNIQUE_DESC(x) EASY_TOKEN_CONCATENATE(unique_profiler_descriptor_, x)
|
||||
|
||||
#ifdef USING_EASY_PROFILER
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace profiler
|
||||
{
|
||||
template <const bool> struct NameSwitch;
|
||||
|
||||
class ForceConstStr EASY_FINAL
|
||||
{
|
||||
friend NameSwitch<true>;
|
||||
friend NameSwitch<false>;
|
||||
|
||||
const char* c_str;
|
||||
|
||||
public:
|
||||
|
||||
ForceConstStr() = delete;
|
||||
ForceConstStr(const ForceConstStr&) = delete;
|
||||
ForceConstStr(ForceConstStr&&) = delete;
|
||||
ForceConstStr& operator = (const ForceConstStr&) = delete;
|
||||
ForceConstStr& operator = (ForceConstStr&&) = delete;
|
||||
|
||||
explicit EASY_CONSTEXPR_FCN ForceConstStr(const char* _str) : c_str(_str) {}
|
||||
explicit ForceConstStr(const ::std::string& _str) : c_str(_str.c_str()) {}
|
||||
};
|
||||
|
||||
template <const bool IS_REF> struct NameSwitch EASY_FINAL
|
||||
{
|
||||
static const char* runtime_name(const char* name) { return name; }
|
||||
static const char* runtime_name(const ::std::string& name) { return name.c_str(); }
|
||||
static EASY_CONSTEXPR_FCN const char* runtime_name(const ForceConstStr&) { return ""; }
|
||||
|
||||
template <class T>
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const T&, const char* autoGeneratedName) { return autoGeneratedName; }
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const char*, const char* autoGeneratedName) { return autoGeneratedName; }
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const ForceConstStr& name, const char*) { return name.c_str; }
|
||||
};
|
||||
|
||||
template <> struct NameSwitch<true> EASY_FINAL
|
||||
{
|
||||
static EASY_CONSTEXPR_FCN const char* runtime_name(const char*) { return ""; }
|
||||
static EASY_CONSTEXPR_FCN const char* runtime_name(const ForceConstStr&) { return ""; }
|
||||
static const char* runtime_name(const ::std::string& name) { return name.c_str(); }
|
||||
|
||||
template <class T>
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const T&, const char* autoGeneratedName) { return autoGeneratedName; }
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const char* name, const char*) { return name; }
|
||||
static EASY_CONSTEXPR_FCN const char* compiletime_name(const ForceConstStr& name, const char*) { return name.c_str; }
|
||||
};
|
||||
|
||||
//***********************************************
|
||||
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color(TArgs...);
|
||||
|
||||
template <>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color<>() {
|
||||
return ::profiler::colors::Default;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color(T) {
|
||||
return ::profiler::colors::Default;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color<color_t>(color_t _color) {
|
||||
return _color;
|
||||
}
|
||||
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color(color_t _color, TArgs...) {
|
||||
return _color;
|
||||
}
|
||||
|
||||
template <class T, class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN color_t extract_color(T, TArgs... _args) {
|
||||
return extract_color(_args...);
|
||||
}
|
||||
|
||||
//***********************************************
|
||||
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag(TArgs...);
|
||||
|
||||
template <>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag<>() {
|
||||
return ::profiler::ON;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag(T) {
|
||||
return ::profiler::ON;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag(EasyBlockStatus _flag) {
|
||||
return _flag;
|
||||
}
|
||||
|
||||
template <class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag(EasyBlockStatus _flag, TArgs...) {
|
||||
return _flag;
|
||||
}
|
||||
|
||||
template <class T, class ... TArgs>
|
||||
inline EASY_CONSTEXPR_FCN EasyBlockStatus extract_enable_flag(T, TArgs... _args) {
|
||||
return extract_enable_flag(_args...);
|
||||
}
|
||||
|
||||
//***********************************************
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
# define EASY_UNIQUE_LINE_ID __FILE__ ":" EASY_STRINGIFICATION(__LINE__)
|
||||
# define EASY_COMPILETIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::compiletime_name(name, EASY_UNIQUE_LINE_ID)
|
||||
# define EASY_RUNTIME_NAME(name) ::profiler::NameSwitch<::std::is_reference<decltype(name)>::value>::runtime_name(name)
|
||||
# define EASY_CONST_NAME(name) ::profiler::ForceConstStr(name)
|
||||
|
||||
#else
|
||||
|
||||
# define EASY_CONST_NAME(name)
|
||||
|
||||
#endif // USING_EASY_PROFILER
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EASY_PROFILER_AUX_H
|
||||
@@ -0,0 +1,413 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_COLORS_H
|
||||
#define EASY_PROFILER_COLORS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace profiler {
|
||||
|
||||
using color_t = uint32_t; // Standard four-byte ARGB color format
|
||||
|
||||
namespace colors {
|
||||
|
||||
///< Change alpha for color. Only 8 major bytes (0xff000000) used from alpha.
|
||||
inline EASY_CONSTEXPR_FCN color_t modify_alpha32(color_t _color, color_t _alpha) {
|
||||
return (_alpha & 0xff000000) | (_color & 0x00ffffff);
|
||||
}
|
||||
|
||||
///< Change alpha for color.
|
||||
inline EASY_CONSTEXPR_FCN color_t modify_alpha8(color_t _color, uint8_t _alpha) {
|
||||
return (static_cast<color_t>(_alpha) << 24) | (_color & 0x00ffffff);
|
||||
}
|
||||
|
||||
///< Create color from ARGB components.
|
||||
inline EASY_CONSTEXPR_FCN color_t color(uint8_t _red, uint8_t _green, uint8_t _blue, uint8_t _alpha = 0xff) {
|
||||
return (static_cast<color_t>(_alpha) << 24) | (static_cast<color_t>(_red) << 16) | (static_cast<color_t>(_green) << 8) | static_cast<color_t>(_blue);
|
||||
}
|
||||
|
||||
#if !defined(EASY_OPTION_BUILTIN_COLORS) || EASY_OPTION_BUILTIN_COLORS != 0
|
||||
// Google Material Design colors
|
||||
// See https://material.google.com/style/color.html
|
||||
|
||||
EASY_CONSTEXPR color_t Red50 = 0xffffebee;
|
||||
EASY_CONSTEXPR color_t Red100 = 0xffffcdd2;
|
||||
EASY_CONSTEXPR color_t Red200 = 0xffef9a9a;
|
||||
EASY_CONSTEXPR color_t Red300 = 0xffe57373;
|
||||
EASY_CONSTEXPR color_t Red400 = 0xffef5350;
|
||||
EASY_CONSTEXPR color_t Red500 = 0xfff44336;
|
||||
EASY_CONSTEXPR color_t Red600 = 0xffe53935;
|
||||
EASY_CONSTEXPR color_t Red700 = 0xffd32f2f;
|
||||
EASY_CONSTEXPR color_t Red800 = 0xffc62828;
|
||||
EASY_CONSTEXPR color_t Red900 = 0xffb71c1c;
|
||||
EASY_CONSTEXPR color_t RedA100 = 0xffff8a80;
|
||||
EASY_CONSTEXPR color_t RedA200 = 0xffff5252;
|
||||
EASY_CONSTEXPR color_t RedA400 = 0xffff1744;
|
||||
EASY_CONSTEXPR color_t RedA700 = 0xffd50000;
|
||||
|
||||
EASY_CONSTEXPR color_t Pink50 = 0xfffce4ec;
|
||||
EASY_CONSTEXPR color_t Pink100 = 0xfff8bbd0;
|
||||
EASY_CONSTEXPR color_t Pink200 = 0xfff48fb1;
|
||||
EASY_CONSTEXPR color_t Pink300 = 0xfff06292;
|
||||
EASY_CONSTEXPR color_t Pink400 = 0xffec407a;
|
||||
EASY_CONSTEXPR color_t Pink500 = 0xffe91e63;
|
||||
EASY_CONSTEXPR color_t Pink600 = 0xffd81b60;
|
||||
EASY_CONSTEXPR color_t Pink700 = 0xffc2185b;
|
||||
EASY_CONSTEXPR color_t Pink800 = 0xffad1457;
|
||||
EASY_CONSTEXPR color_t Pink900 = 0xff880e4f;
|
||||
EASY_CONSTEXPR color_t PinkA100 = 0xffff80ab;
|
||||
EASY_CONSTEXPR color_t PinkA200 = 0xffff4081;
|
||||
EASY_CONSTEXPR color_t PinkA400 = 0xfff50057;
|
||||
EASY_CONSTEXPR color_t PinkA700 = 0xffc51162;
|
||||
|
||||
EASY_CONSTEXPR color_t Purple50 = 0xfff3e5f5;
|
||||
EASY_CONSTEXPR color_t Purple100 = 0xffe1bee7;
|
||||
EASY_CONSTEXPR color_t Purple200 = 0xffce93d8;
|
||||
EASY_CONSTEXPR color_t Purple300 = 0xffba68c8;
|
||||
EASY_CONSTEXPR color_t Purple400 = 0xffab47bc;
|
||||
EASY_CONSTEXPR color_t Purple500 = 0xff9c27b0;
|
||||
EASY_CONSTEXPR color_t Purple600 = 0xff8e24aa;
|
||||
EASY_CONSTEXPR color_t Purple700 = 0xff7b1fa2;
|
||||
EASY_CONSTEXPR color_t Purple800 = 0xff6a1b9a;
|
||||
EASY_CONSTEXPR color_t Purple900 = 0xff4a148c;
|
||||
EASY_CONSTEXPR color_t PurpleA100 = 0xffea80fc;
|
||||
EASY_CONSTEXPR color_t PurpleA200 = 0xffe040fb;
|
||||
EASY_CONSTEXPR color_t PurpleA400 = 0xffd500f9;
|
||||
EASY_CONSTEXPR color_t PurpleA700 = 0xffaa00ff;
|
||||
|
||||
EASY_CONSTEXPR color_t DeepPurple50 = 0xffede7f6;
|
||||
EASY_CONSTEXPR color_t DeepPurple100 = 0xffd1c4e9;
|
||||
EASY_CONSTEXPR color_t DeepPurple200 = 0xffb39ddb;
|
||||
EASY_CONSTEXPR color_t DeepPurple300 = 0xff9575cd;
|
||||
EASY_CONSTEXPR color_t DeepPurple400 = 0xff7e57c2;
|
||||
EASY_CONSTEXPR color_t DeepPurple500 = 0xff673ab7;
|
||||
EASY_CONSTEXPR color_t DeepPurple600 = 0xff5e35b1;
|
||||
EASY_CONSTEXPR color_t DeepPurple700 = 0xff512da8;
|
||||
EASY_CONSTEXPR color_t DeepPurple800 = 0xff4527a0;
|
||||
EASY_CONSTEXPR color_t DeepPurple900 = 0xff311b92;
|
||||
EASY_CONSTEXPR color_t DeepPurpleA100 = 0xffb388ff;
|
||||
EASY_CONSTEXPR color_t DeepPurpleA200 = 0xff7c4dff;
|
||||
EASY_CONSTEXPR color_t DeepPurpleA400 = 0xff651fff;
|
||||
EASY_CONSTEXPR color_t DeepPurpleA700 = 0xff6200ea;
|
||||
|
||||
EASY_CONSTEXPR color_t Indigo50 = 0xffe8eaf6;
|
||||
EASY_CONSTEXPR color_t Indigo100 = 0xffc5cae9;
|
||||
EASY_CONSTEXPR color_t Indigo200 = 0xff9fa8da;
|
||||
EASY_CONSTEXPR color_t Indigo300 = 0xff7986cb;
|
||||
EASY_CONSTEXPR color_t Indigo400 = 0xff5c6bc0;
|
||||
EASY_CONSTEXPR color_t Indigo500 = 0xff3f51b5;
|
||||
EASY_CONSTEXPR color_t Indigo600 = 0xff3949ab;
|
||||
EASY_CONSTEXPR color_t Indigo700 = 0xff303f9f;
|
||||
EASY_CONSTEXPR color_t Indigo800 = 0xff283593;
|
||||
EASY_CONSTEXPR color_t Indigo900 = 0xff1a237e;
|
||||
EASY_CONSTEXPR color_t IndigoA100 = 0xff8c9eff;
|
||||
EASY_CONSTEXPR color_t IndigoA200 = 0xff536dfe;
|
||||
EASY_CONSTEXPR color_t IndigoA400 = 0xff3d5afe;
|
||||
EASY_CONSTEXPR color_t IndigoA700 = 0xff304ffe;
|
||||
|
||||
EASY_CONSTEXPR color_t Blue50 = 0xffe3f2fd;
|
||||
EASY_CONSTEXPR color_t Blue100 = 0xffbbdefb;
|
||||
EASY_CONSTEXPR color_t Blue200 = 0xff90caf9;
|
||||
EASY_CONSTEXPR color_t Blue300 = 0xff64b5f6;
|
||||
EASY_CONSTEXPR color_t Blue400 = 0xff42a5f5;
|
||||
EASY_CONSTEXPR color_t Blue500 = 0xff2196f3;
|
||||
EASY_CONSTEXPR color_t Blue600 = 0xff1e88e5;
|
||||
EASY_CONSTEXPR color_t Blue700 = 0xff1976d2;
|
||||
EASY_CONSTEXPR color_t Blue800 = 0xff1565c0;
|
||||
EASY_CONSTEXPR color_t Blue900 = 0xff0d47a1;
|
||||
EASY_CONSTEXPR color_t BlueA100 = 0xff82b1ff;
|
||||
EASY_CONSTEXPR color_t BlueA200 = 0xff448aff;
|
||||
EASY_CONSTEXPR color_t BlueA400 = 0xff2979ff;
|
||||
EASY_CONSTEXPR color_t BlueA700 = 0xff2962ff;
|
||||
|
||||
EASY_CONSTEXPR color_t LightBlue50 = 0xffe1f5fe;
|
||||
EASY_CONSTEXPR color_t LightBlue100 = 0xffb3e5fc;
|
||||
EASY_CONSTEXPR color_t LightBlue200 = 0xff81d4fa;
|
||||
EASY_CONSTEXPR color_t LightBlue300 = 0xff4fc3f7;
|
||||
EASY_CONSTEXPR color_t LightBlue400 = 0xff29b6f6;
|
||||
EASY_CONSTEXPR color_t LightBlue500 = 0xff03a9f4;
|
||||
EASY_CONSTEXPR color_t LightBlue600 = 0xff039be5;
|
||||
EASY_CONSTEXPR color_t LightBlue700 = 0xff0288d1;
|
||||
EASY_CONSTEXPR color_t LightBlue800 = 0xff0277bd;
|
||||
EASY_CONSTEXPR color_t LightBlue900 = 0xff01579b;
|
||||
EASY_CONSTEXPR color_t LightBlueA100 = 0xff80d8ff;
|
||||
EASY_CONSTEXPR color_t LightBlueA200 = 0xff40c4ff;
|
||||
EASY_CONSTEXPR color_t LightBlueA400 = 0xff00b0ff;
|
||||
EASY_CONSTEXPR color_t LightBlueA700 = 0xff0091ea;
|
||||
|
||||
EASY_CONSTEXPR color_t Cyan50 = 0xffe0f7fa;
|
||||
EASY_CONSTEXPR color_t Cyan100 = 0xffb2ebf2;
|
||||
EASY_CONSTEXPR color_t Cyan200 = 0xff80deea;
|
||||
EASY_CONSTEXPR color_t Cyan300 = 0xff4dd0e1;
|
||||
EASY_CONSTEXPR color_t Cyan400 = 0xff26c6da;
|
||||
EASY_CONSTEXPR color_t Cyan500 = 0xff00bcd4;
|
||||
EASY_CONSTEXPR color_t Cyan600 = 0xff00acc1;
|
||||
EASY_CONSTEXPR color_t Cyan700 = 0xff0097a7;
|
||||
EASY_CONSTEXPR color_t Cyan800 = 0xff00838f;
|
||||
EASY_CONSTEXPR color_t Cyan900 = 0xff006064;
|
||||
EASY_CONSTEXPR color_t CyanA100 = 0xff84ffff;
|
||||
EASY_CONSTEXPR color_t CyanA200 = 0xff18ffff;
|
||||
EASY_CONSTEXPR color_t CyanA400 = 0xff00e5ff;
|
||||
EASY_CONSTEXPR color_t CyanA700 = 0xff00b8d4;
|
||||
|
||||
EASY_CONSTEXPR color_t Teal50 = 0xffe0f2f1;
|
||||
EASY_CONSTEXPR color_t Teal100 = 0xffb2dfdb;
|
||||
EASY_CONSTEXPR color_t Teal200 = 0xff80cbc4;
|
||||
EASY_CONSTEXPR color_t Teal300 = 0xff4db6ac;
|
||||
EASY_CONSTEXPR color_t Teal400 = 0xff26a69a;
|
||||
EASY_CONSTEXPR color_t Teal500 = 0xff009688;
|
||||
EASY_CONSTEXPR color_t Teal600 = 0xff00897b;
|
||||
EASY_CONSTEXPR color_t Teal700 = 0xff00796b;
|
||||
EASY_CONSTEXPR color_t Teal800 = 0xff00695c;
|
||||
EASY_CONSTEXPR color_t Teal900 = 0xff004d40;
|
||||
EASY_CONSTEXPR color_t TealA100 = 0xffa7ffeb;
|
||||
EASY_CONSTEXPR color_t TealA200 = 0xff64ffda;
|
||||
EASY_CONSTEXPR color_t TealA400 = 0xff1de9b6;
|
||||
EASY_CONSTEXPR color_t TealA700 = 0xff00bfa5;
|
||||
|
||||
EASY_CONSTEXPR color_t Green50 = 0xffe8f5e9;
|
||||
EASY_CONSTEXPR color_t Green100 = 0xffc8e6c9;
|
||||
EASY_CONSTEXPR color_t Green200 = 0xffa5d6a7;
|
||||
EASY_CONSTEXPR color_t Green300 = 0xff81c784;
|
||||
EASY_CONSTEXPR color_t Green400 = 0xff66bb6a;
|
||||
EASY_CONSTEXPR color_t Green500 = 0xff4caf50;
|
||||
EASY_CONSTEXPR color_t Green600 = 0xff43a047;
|
||||
EASY_CONSTEXPR color_t Green700 = 0xff388e3c;
|
||||
EASY_CONSTEXPR color_t Green800 = 0xff2e7d32;
|
||||
EASY_CONSTEXPR color_t Green900 = 0xff1b5e20;
|
||||
EASY_CONSTEXPR color_t GreenA100 = 0xffb9f6ca;
|
||||
EASY_CONSTEXPR color_t GreenA200 = 0xff69f0ae;
|
||||
EASY_CONSTEXPR color_t GreenA400 = 0xff00e676;
|
||||
EASY_CONSTEXPR color_t GreenA700 = 0xff00c853;
|
||||
|
||||
EASY_CONSTEXPR color_t LightGreen50 = 0xfff1f8e9;
|
||||
EASY_CONSTEXPR color_t LightGreen100 = 0xffdcedc8;
|
||||
EASY_CONSTEXPR color_t LightGreen200 = 0xffc5e1a5;
|
||||
EASY_CONSTEXPR color_t LightGreen300 = 0xffaed581;
|
||||
EASY_CONSTEXPR color_t LightGreen400 = 0xff9ccc65;
|
||||
EASY_CONSTEXPR color_t LightGreen500 = 0xff8bc34a;
|
||||
EASY_CONSTEXPR color_t LightGreen600 = 0xff7cb342;
|
||||
EASY_CONSTEXPR color_t LightGreen700 = 0xff689f38;
|
||||
EASY_CONSTEXPR color_t LightGreen800 = 0xff558b2f;
|
||||
EASY_CONSTEXPR color_t LightGreen900 = 0xff33691e;
|
||||
EASY_CONSTEXPR color_t LightGreenA100 = 0xffccff90;
|
||||
EASY_CONSTEXPR color_t LightGreenA200 = 0xffb2ff59;
|
||||
EASY_CONSTEXPR color_t LightGreenA400 = 0xff76ff03;
|
||||
EASY_CONSTEXPR color_t LightGreenA700 = 0xff64dd17;
|
||||
|
||||
EASY_CONSTEXPR color_t Lime50 = 0xfff9ebe7;
|
||||
EASY_CONSTEXPR color_t Lime100 = 0xfff0f4c3;
|
||||
EASY_CONSTEXPR color_t Lime200 = 0xffe6ee9c;
|
||||
EASY_CONSTEXPR color_t Lime300 = 0xffdce775;
|
||||
EASY_CONSTEXPR color_t Lime400 = 0xffd4e157;
|
||||
EASY_CONSTEXPR color_t Lime500 = 0xffcddc39;
|
||||
EASY_CONSTEXPR color_t Lime600 = 0xffc0ca33;
|
||||
EASY_CONSTEXPR color_t Lime700 = 0xffafb42b;
|
||||
EASY_CONSTEXPR color_t Lime800 = 0xff9e9d24;
|
||||
EASY_CONSTEXPR color_t Lime900 = 0xff827717;
|
||||
EASY_CONSTEXPR color_t LimeA100 = 0xfff4ff81;
|
||||
EASY_CONSTEXPR color_t LimeA200 = 0xffeeff41;
|
||||
EASY_CONSTEXPR color_t LimeA400 = 0xffc6ff00;
|
||||
EASY_CONSTEXPR color_t LimeA700 = 0xffaeea00;
|
||||
|
||||
EASY_CONSTEXPR color_t Yellow50 = 0xfffffde7;
|
||||
EASY_CONSTEXPR color_t Yellow100 = 0xfffff9c4;
|
||||
EASY_CONSTEXPR color_t Yellow200 = 0xfffff59d;
|
||||
EASY_CONSTEXPR color_t Yellow300 = 0xfffff176;
|
||||
EASY_CONSTEXPR color_t Yellow400 = 0xffffee58;
|
||||
EASY_CONSTEXPR color_t Yellow500 = 0xffffeb3b;
|
||||
EASY_CONSTEXPR color_t Yellow600 = 0xfffdd835;
|
||||
EASY_CONSTEXPR color_t Yellow700 = 0xfffbc02d;
|
||||
EASY_CONSTEXPR color_t Yellow800 = 0xfff9a825;
|
||||
EASY_CONSTEXPR color_t Yellow900 = 0xfff57f17;
|
||||
EASY_CONSTEXPR color_t YellowA100 = 0xffffff8d;
|
||||
EASY_CONSTEXPR color_t YellowA200 = 0xffffff00;
|
||||
EASY_CONSTEXPR color_t YellowA400 = 0xffffea00;
|
||||
EASY_CONSTEXPR color_t YellowA700 = 0xffffd600;
|
||||
|
||||
EASY_CONSTEXPR color_t Amber50 = 0xfffff8e1;
|
||||
EASY_CONSTEXPR color_t Amber100 = 0xffffecb3;
|
||||
EASY_CONSTEXPR color_t Amber200 = 0xffffe082;
|
||||
EASY_CONSTEXPR color_t Amber300 = 0xffffd54f;
|
||||
EASY_CONSTEXPR color_t Amber400 = 0xffffca28;
|
||||
EASY_CONSTEXPR color_t Amber500 = 0xffffc107;
|
||||
EASY_CONSTEXPR color_t Amber600 = 0xffffb300;
|
||||
EASY_CONSTEXPR color_t Amber700 = 0xffffa000;
|
||||
EASY_CONSTEXPR color_t Amber800 = 0xffff8f00;
|
||||
EASY_CONSTEXPR color_t Amber900 = 0xffff6f00;
|
||||
EASY_CONSTEXPR color_t AmberA100 = 0xffffe57f;
|
||||
EASY_CONSTEXPR color_t AmberA200 = 0xffffd740;
|
||||
EASY_CONSTEXPR color_t AmberA400 = 0xffffc400;
|
||||
EASY_CONSTEXPR color_t AmberA700 = 0xffffab00;
|
||||
|
||||
EASY_CONSTEXPR color_t Orange50 = 0xfffff3e0;
|
||||
EASY_CONSTEXPR color_t Orange100 = 0xffffe0b2;
|
||||
EASY_CONSTEXPR color_t Orange200 = 0xffffcc80;
|
||||
EASY_CONSTEXPR color_t Orange300 = 0xffffb74d;
|
||||
EASY_CONSTEXPR color_t Orange400 = 0xffffa726;
|
||||
EASY_CONSTEXPR color_t Orange500 = 0xffff9800;
|
||||
EASY_CONSTEXPR color_t Orange600 = 0xfffb8c00;
|
||||
EASY_CONSTEXPR color_t Orange700 = 0xfff57c00;
|
||||
EASY_CONSTEXPR color_t Orange800 = 0xffef6c00;
|
||||
EASY_CONSTEXPR color_t Orange900 = 0xffe65100;
|
||||
EASY_CONSTEXPR color_t OrangeA100 = 0xffffd180;
|
||||
EASY_CONSTEXPR color_t OrangeA200 = 0xffffab40;
|
||||
EASY_CONSTEXPR color_t OrangeA400 = 0xffff9100;
|
||||
EASY_CONSTEXPR color_t OrangeA700 = 0xffff6d00;
|
||||
|
||||
EASY_CONSTEXPR color_t DeepOrange50 = 0xfffbe9e7;
|
||||
EASY_CONSTEXPR color_t DeepOrange100 = 0xffffccbc;
|
||||
EASY_CONSTEXPR color_t DeepOrange200 = 0xffffab91;
|
||||
EASY_CONSTEXPR color_t DeepOrange300 = 0xffff8a65;
|
||||
EASY_CONSTEXPR color_t DeepOrange400 = 0xffff7043;
|
||||
EASY_CONSTEXPR color_t DeepOrange500 = 0xffff5722;
|
||||
EASY_CONSTEXPR color_t DeepOrange600 = 0xfff4511e;
|
||||
EASY_CONSTEXPR color_t DeepOrange700 = 0xffe64a19;
|
||||
EASY_CONSTEXPR color_t DeepOrange800 = 0xffd84315;
|
||||
EASY_CONSTEXPR color_t DeepOrange900 = 0xffbf360c;
|
||||
EASY_CONSTEXPR color_t DeepOrangeA100 = 0xffff9e80;
|
||||
EASY_CONSTEXPR color_t DeepOrangeA200 = 0xffff6e40;
|
||||
EASY_CONSTEXPR color_t DeepOrangeA400 = 0xffff3d00;
|
||||
EASY_CONSTEXPR color_t DeepOrangeA700 = 0xffdd2c00;
|
||||
|
||||
EASY_CONSTEXPR color_t Brown50 = 0xffefebe9;
|
||||
EASY_CONSTEXPR color_t Brown100 = 0xffd7ccc8;
|
||||
EASY_CONSTEXPR color_t Brown200 = 0xffbcaaa4;
|
||||
EASY_CONSTEXPR color_t Brown300 = 0xffa1887f;
|
||||
EASY_CONSTEXPR color_t Brown400 = 0xff8d6e63;
|
||||
EASY_CONSTEXPR color_t Brown500 = 0xff795548;
|
||||
EASY_CONSTEXPR color_t Brown600 = 0xff6d4c41;
|
||||
EASY_CONSTEXPR color_t Brown700 = 0xff5d4037;
|
||||
EASY_CONSTEXPR color_t Brown800 = 0xff4e342e;
|
||||
EASY_CONSTEXPR color_t Brown900 = 0xff3e2723;
|
||||
|
||||
EASY_CONSTEXPR color_t Grey50 = 0xfffafafa;
|
||||
EASY_CONSTEXPR color_t Grey100 = 0xfff5f5f5;
|
||||
EASY_CONSTEXPR color_t Grey200 = 0xffeeeeee;
|
||||
EASY_CONSTEXPR color_t Grey300 = 0xffe0e0e0;
|
||||
EASY_CONSTEXPR color_t Grey400 = 0xffbdbdbd;
|
||||
EASY_CONSTEXPR color_t Grey500 = 0xff9e9e9e;
|
||||
EASY_CONSTEXPR color_t Grey600 = 0xff757575;
|
||||
EASY_CONSTEXPR color_t Grey700 = 0xff616161;
|
||||
EASY_CONSTEXPR color_t Grey800 = 0xff424242;
|
||||
EASY_CONSTEXPR color_t Grey900 = 0xff212121;
|
||||
|
||||
EASY_CONSTEXPR color_t BlueGrey50 = 0xffeceff1;
|
||||
EASY_CONSTEXPR color_t BlueGrey100 = 0xffcfd8dc;
|
||||
EASY_CONSTEXPR color_t BlueGrey200 = 0xffb0bec5;
|
||||
EASY_CONSTEXPR color_t BlueGrey300 = 0xff90a4ae;
|
||||
EASY_CONSTEXPR color_t BlueGrey400 = 0xff78909c;
|
||||
EASY_CONSTEXPR color_t BlueGrey500 = 0xff607d8b;
|
||||
EASY_CONSTEXPR color_t BlueGrey600 = 0xff546e7a;
|
||||
EASY_CONSTEXPR color_t BlueGrey700 = 0xff455a64;
|
||||
EASY_CONSTEXPR color_t BlueGrey800 = 0xff37474f;
|
||||
EASY_CONSTEXPR color_t BlueGrey900 = 0xff263238;
|
||||
|
||||
EASY_CONSTEXPR color_t Black = 0xff000000;
|
||||
EASY_CONSTEXPR color_t White = 0xffffffff;
|
||||
EASY_CONSTEXPR color_t Null = 0x00000000;
|
||||
|
||||
|
||||
EASY_CONSTEXPR color_t Red = Red500;
|
||||
EASY_CONSTEXPR color_t DarkRed = Red900;
|
||||
EASY_CONSTEXPR color_t Coral = Red200;
|
||||
EASY_CONSTEXPR color_t RichRed = 0xffff0000;
|
||||
EASY_CONSTEXPR color_t Pink = Pink500;
|
||||
EASY_CONSTEXPR color_t Rose = PinkA100;
|
||||
EASY_CONSTEXPR color_t Purple = Purple500;
|
||||
EASY_CONSTEXPR color_t Magenta = PurpleA200;
|
||||
EASY_CONSTEXPR color_t DarkMagenta = PurpleA700;
|
||||
EASY_CONSTEXPR color_t DeepPurple = DeepPurple500;
|
||||
EASY_CONSTEXPR color_t Indigo = Indigo500;
|
||||
EASY_CONSTEXPR color_t Blue = Blue500;
|
||||
EASY_CONSTEXPR color_t DarkBlue = Blue900;
|
||||
EASY_CONSTEXPR color_t RichBlue = 0xff0000ff;
|
||||
EASY_CONSTEXPR color_t LightBlue = LightBlue500;
|
||||
EASY_CONSTEXPR color_t SkyBlue = LightBlueA100;
|
||||
EASY_CONSTEXPR color_t Navy = LightBlue800;
|
||||
EASY_CONSTEXPR color_t Cyan = Cyan500;
|
||||
EASY_CONSTEXPR color_t DarkCyan = Cyan900;
|
||||
EASY_CONSTEXPR color_t Teal = Teal500;
|
||||
EASY_CONSTEXPR color_t DarkTeal = Teal900;
|
||||
EASY_CONSTEXPR color_t Green = Green500;
|
||||
EASY_CONSTEXPR color_t DarkGreen = Green900;
|
||||
EASY_CONSTEXPR color_t RichGreen = 0xff00ff00;
|
||||
EASY_CONSTEXPR color_t LightGreen = LightGreen500;
|
||||
EASY_CONSTEXPR color_t Mint = LightGreen900;
|
||||
EASY_CONSTEXPR color_t Lime = Lime500;
|
||||
EASY_CONSTEXPR color_t Olive = Lime900;
|
||||
EASY_CONSTEXPR color_t Yellow = Yellow500;
|
||||
EASY_CONSTEXPR color_t RichYellow = YellowA200;
|
||||
EASY_CONSTEXPR color_t Amber = Amber500;
|
||||
EASY_CONSTEXPR color_t Gold = Amber300;
|
||||
EASY_CONSTEXPR color_t PaleGold = AmberA100;
|
||||
EASY_CONSTEXPR color_t Orange = Orange500;
|
||||
EASY_CONSTEXPR color_t Skin = Orange100;
|
||||
EASY_CONSTEXPR color_t DeepOrange = DeepOrange500;
|
||||
EASY_CONSTEXPR color_t Brick = DeepOrange900;
|
||||
EASY_CONSTEXPR color_t Brown = Brown500;
|
||||
EASY_CONSTEXPR color_t DarkBrown = Brown900;
|
||||
EASY_CONSTEXPR color_t CreamWhite = Orange50;
|
||||
EASY_CONSTEXPR color_t Wheat = Amber100;
|
||||
EASY_CONSTEXPR color_t Grey = Grey500;
|
||||
EASY_CONSTEXPR color_t Dark = Grey900;
|
||||
EASY_CONSTEXPR color_t Silver = Grey300;
|
||||
EASY_CONSTEXPR color_t BlueGrey = BlueGrey500;
|
||||
|
||||
EASY_CONSTEXPR color_t Default = Wheat;
|
||||
#else
|
||||
EASY_CONSTEXPR color_t Default = 0xffffecb3;
|
||||
#endif // #if !defined(EASY_OPTION_BUILTIN_COLORS) || EASY_OPTION_BUILTIN_COLORS == 0
|
||||
|
||||
} // END of namespace colors.
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EASY_PROFILER_COLORS_H
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_IN_USE_H
|
||||
#define EASY_PROFILER_IN_USE_H
|
||||
|
||||
//
|
||||
// BUILD_WITH_EASY_PROFILER is defined in CMakeLists.txt if your project is linked to easy_profiler.
|
||||
//
|
||||
|
||||
//
|
||||
// DISABLE_EASY_PROFILER may be defined manually in source-file before #include <easy/profiler.h>
|
||||
// to disable profiler for certain source-file or project.
|
||||
//
|
||||
|
||||
#if defined(BUILD_WITH_EASY_PROFILER) && !defined(DISABLE_EASY_PROFILER)
|
||||
|
||||
/**
|
||||
\defgroup profiler EasyProfiler
|
||||
*/
|
||||
|
||||
|
||||
/** Indicates that EasyProfiler is used.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define USING_EASY_PROFILER
|
||||
|
||||
#endif
|
||||
|
||||
#endif // EASY_PROFILER_IN_USE_H
|
||||
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_PUBLIC_TYPES_H
|
||||
#define EASY_PROFILER_PUBLIC_TYPES_H
|
||||
|
||||
#include <easy/details/profiler_aux.h>
|
||||
|
||||
class NonscopedBlock;
|
||||
class ProfileManager;
|
||||
struct ThreadStorage;
|
||||
|
||||
namespace profiler {
|
||||
|
||||
using timestamp_t = uint64_t;
|
||||
using thread_id_t = uint64_t;
|
||||
using block_id_t = uint32_t;
|
||||
|
||||
enum class BlockType : uint8_t
|
||||
{
|
||||
Event = 0,
|
||||
Block,
|
||||
Value,
|
||||
|
||||
TypesCount
|
||||
};
|
||||
using block_type_t = BlockType;
|
||||
|
||||
enum Duration : uint8_t
|
||||
{
|
||||
TICKS = 0, ///< CPU ticks
|
||||
MICROSECONDS ///< Microseconds
|
||||
};
|
||||
|
||||
//***********************************************
|
||||
|
||||
#pragma pack(push,1)
|
||||
class PROFILER_API BaseBlockDescriptor
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
friend ::ThreadStorage;
|
||||
|
||||
protected:
|
||||
|
||||
block_id_t m_id; ///< This descriptor id (We can afford this spending because there are much more blocks than descriptors)
|
||||
int32_t m_line; ///< Line number in the source file
|
||||
color_t m_color; ///< Color of the block packed into 1-byte structure
|
||||
block_type_t m_type; ///< Type of the block (See BlockType)
|
||||
EasyBlockStatus m_status; ///< If false then blocks with such id() will not be stored by profiler during profile session
|
||||
|
||||
explicit BaseBlockDescriptor(block_id_t _id, EasyBlockStatus _status, int _line, block_type_t _block_type, color_t _color) EASY_NOEXCEPT;
|
||||
|
||||
public:
|
||||
|
||||
BaseBlockDescriptor() = delete;
|
||||
|
||||
inline block_id_t id() const EASY_NOEXCEPT { return m_id; }
|
||||
inline int32_t line() const EASY_NOEXCEPT { return m_line; }
|
||||
inline color_t color() const EASY_NOEXCEPT { return m_color; }
|
||||
inline block_type_t type() const EASY_NOEXCEPT { return m_type; }
|
||||
inline EasyBlockStatus status() const EASY_NOEXCEPT { return m_status; }
|
||||
|
||||
}; // END of class BaseBlockDescriptor.
|
||||
|
||||
//***********************************************
|
||||
|
||||
class PROFILER_API Event
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
|
||||
protected:
|
||||
|
||||
timestamp_t m_begin;
|
||||
timestamp_t m_end;
|
||||
|
||||
public:
|
||||
|
||||
Event() = delete;
|
||||
|
||||
Event(const Event&) = default;
|
||||
explicit Event(timestamp_t _begin_time) EASY_NOEXCEPT;
|
||||
explicit Event(timestamp_t _begin_time, timestamp_t _end_time) EASY_NOEXCEPT;
|
||||
|
||||
inline timestamp_t begin() const EASY_NOEXCEPT { return m_begin; }
|
||||
inline timestamp_t end() const EASY_NOEXCEPT { return m_end; }
|
||||
inline timestamp_t duration() const EASY_NOEXCEPT { return m_end - m_begin; }
|
||||
|
||||
}; // END class Event.
|
||||
|
||||
class PROFILER_API BaseBlockData : public Event
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
|
||||
protected:
|
||||
|
||||
block_id_t m_id;
|
||||
|
||||
public:
|
||||
|
||||
BaseBlockData() = delete;
|
||||
|
||||
BaseBlockData(const BaseBlockData&) = default;
|
||||
explicit BaseBlockData(timestamp_t _begin_time, block_id_t _id) EASY_NOEXCEPT;
|
||||
explicit BaseBlockData(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _id) EASY_NOEXCEPT;
|
||||
|
||||
inline block_id_t id() const EASY_NOEXCEPT { return m_id; }
|
||||
inline void setId(block_id_t _id) EASY_NOEXCEPT { m_id = _id; }
|
||||
|
||||
}; // END of class BaseBlockData.
|
||||
#pragma pack(pop)
|
||||
|
||||
//***********************************************
|
||||
|
||||
class PROFILER_API Block : public BaseBlockData
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
friend ::ThreadStorage;
|
||||
friend ::NonscopedBlock;
|
||||
|
||||
const char* m_name;
|
||||
EasyBlockStatus m_status;
|
||||
bool m_isScoped;
|
||||
|
||||
private:
|
||||
|
||||
void start();
|
||||
void start(timestamp_t _time) EASY_NOEXCEPT;
|
||||
void finish();
|
||||
void finish(timestamp_t _time) EASY_NOEXCEPT;
|
||||
inline bool finished() const EASY_NOEXCEPT { return m_end >= m_begin; }
|
||||
inline EasyBlockStatus status() const EASY_NOEXCEPT { return m_status; }
|
||||
inline void setStatus(EasyBlockStatus _status) EASY_NOEXCEPT { m_status = _status; }
|
||||
|
||||
public:
|
||||
|
||||
Block(const Block&) = delete;
|
||||
Block& operator = (const Block&) = delete;
|
||||
|
||||
Block(Block&& that) EASY_NOEXCEPT;
|
||||
Block(const BaseBlockDescriptor* _desc, const char* _runtimeName, bool _scoped = true) EASY_NOEXCEPT;
|
||||
Block(timestamp_t _begin_time, block_id_t _id, const char* _runtimeName) EASY_NOEXCEPT;
|
||||
Block(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _id, const char* _runtimeName) EASY_NOEXCEPT;
|
||||
~Block();
|
||||
|
||||
inline const char* name() const EASY_NOEXCEPT { return m_name; }
|
||||
|
||||
}; // END of class Block.
|
||||
|
||||
//***********************************************
|
||||
|
||||
class PROFILER_API ThreadGuard EASY_FINAL
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
thread_id_t m_id = 0;
|
||||
|
||||
public:
|
||||
|
||||
~ThreadGuard();
|
||||
|
||||
}; // END of class ThreadGuard.
|
||||
|
||||
EASY_CONSTEXPR uint16_t MAX_BLOCK_DATA_SIZE = 2048 + 512 + 256; ///< Estimated maximum size of block dynamic name or EASY_VALUE data size
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
#endif // EASY_PROFILER_PUBLIC_TYPES_H
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_NET_H
|
||||
#define EASY_NET_H
|
||||
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace profiler { namespace net {
|
||||
|
||||
EASY_CONSTEXPR uint32_t EASY_MESSAGE_SIGN = 20160909;
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
enum class MessageType : uint8_t
|
||||
{
|
||||
Undefined = 0,
|
||||
|
||||
Request_Start_Capture,
|
||||
Reply_Capturing_Started,
|
||||
Request_Stop_Capture,
|
||||
|
||||
Reply_Blocks,
|
||||
Reply_Blocks_End,
|
||||
|
||||
Connection_Accepted,
|
||||
|
||||
Request_Blocks_Description,
|
||||
Reply_Blocks_Description,
|
||||
Reply_Blocks_Description_End,
|
||||
|
||||
Change_Block_Status,
|
||||
Change_Event_Tracing_Status,
|
||||
Change_Event_Tracing_Priority,
|
||||
|
||||
Ping,
|
||||
|
||||
Request_MainThread_FPS,
|
||||
Reply_MainThread_FPS,
|
||||
};
|
||||
|
||||
struct Message
|
||||
{
|
||||
uint32_t magic_number = EASY_MESSAGE_SIGN;
|
||||
MessageType type = MessageType::Undefined;
|
||||
|
||||
bool isEasyNetMessage() const EASY_NOEXCEPT {
|
||||
return EASY_MESSAGE_SIGN == magic_number;
|
||||
}
|
||||
|
||||
explicit Message(MessageType _t) EASY_NOEXCEPT : type(_t) { }
|
||||
|
||||
Message() = default;
|
||||
};
|
||||
|
||||
struct DataMessage : public Message
|
||||
{
|
||||
uint32_t size = 0; // bytes
|
||||
|
||||
explicit DataMessage(MessageType _t = MessageType::Reply_Blocks) : Message(_t) {}
|
||||
explicit DataMessage(uint32_t _s, MessageType _t = MessageType::Reply_Blocks) : Message(_t), size(_s) {}
|
||||
|
||||
const char* data() const { return reinterpret_cast<const char*>(this) + sizeof(DataMessage); }
|
||||
};
|
||||
|
||||
struct BlockStatusMessage : public Message
|
||||
{
|
||||
uint32_t id;
|
||||
uint8_t status;
|
||||
|
||||
explicit BlockStatusMessage(uint32_t _id, uint8_t _status)
|
||||
: Message(MessageType::Change_Block_Status), id(_id), status(_status) { }
|
||||
|
||||
BlockStatusMessage() = delete;
|
||||
};
|
||||
|
||||
struct EasyProfilerStatus : public Message
|
||||
{
|
||||
bool isProfilerEnabled;
|
||||
bool isEventTracingEnabled;
|
||||
bool isLowPriorityEventTracing;
|
||||
|
||||
explicit EasyProfilerStatus(bool _enabled, bool _ETenabled, bool _ETlowp)
|
||||
: Message(MessageType::Connection_Accepted)
|
||||
, isProfilerEnabled(_enabled)
|
||||
, isEventTracingEnabled(_ETenabled)
|
||||
, isLowPriorityEventTracing(_ETlowp)
|
||||
{
|
||||
}
|
||||
|
||||
EasyProfilerStatus() = delete;
|
||||
};
|
||||
|
||||
struct BoolMessage : public Message
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
explicit BoolMessage(MessageType _t, bool _flag = false)
|
||||
: Message(_t), flag(_flag) { }
|
||||
|
||||
BoolMessage() = default;
|
||||
};
|
||||
|
||||
struct TimestampMessage : public Message
|
||||
{
|
||||
uint32_t maxValue = 0;
|
||||
uint32_t avgValue = 0;
|
||||
|
||||
explicit TimestampMessage(MessageType _t, uint32_t _maxValue, uint32_t _avgValue)
|
||||
: Message(_t), maxValue(_maxValue), avgValue(_avgValue) { }
|
||||
|
||||
TimestampMessage() = default;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
}//net
|
||||
|
||||
}//profiler
|
||||
|
||||
#endif // EASY_NET_H
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef EASY_PROPROTOCOL_H
|
||||
#define EASY_PROPROTOCOL_H
|
||||
///C++
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
///this
|
||||
#include <easy/serialized_block.h>
|
||||
//#include <easy/profiler.h>
|
||||
|
||||
///for actual version vistit https://github.com/yse/easy_profiler/wiki/.prof-file-format-v1.3.0
|
||||
|
||||
namespace profiler {
|
||||
|
||||
namespace reader {
|
||||
|
||||
struct BlockDescriptor;
|
||||
|
||||
struct BlocksInfo //12
|
||||
{
|
||||
uint32_t totalBlocksCount; //4 bytes
|
||||
uint64_t totalBlocksMemory; //8 bytes
|
||||
};
|
||||
|
||||
struct DescriptorsInfo //12
|
||||
{
|
||||
uint32_t allDescriptorsCount; //4 bytes
|
||||
uint64_t allDescriptorsMemory; //8 bytes
|
||||
};
|
||||
|
||||
struct FileHeader //64
|
||||
{
|
||||
uint32_t signature; //4
|
||||
uint32_t version; //4
|
||||
uint64_t processId; //8
|
||||
int64_t cpuFrequency; //8
|
||||
uint64_t beginTime; //8
|
||||
uint64_t endTime; //8
|
||||
BlocksInfo serializedBlocksInfo; //12
|
||||
DescriptorsInfo blocksDescriptorInfo; //12
|
||||
};
|
||||
|
||||
struct BlockInfo
|
||||
{
|
||||
uint64_t beginTime;
|
||||
uint64_t endTime;
|
||||
const BlockDescriptor* descriptor;
|
||||
uint32_t blockIndex;
|
||||
};
|
||||
|
||||
struct ContextSwitchEvent
|
||||
{
|
||||
uint64_t beginTime;
|
||||
uint64_t endTime;
|
||||
uint64_t targetThreadId;
|
||||
std::string targetProcess; ///< Contains process id and process name
|
||||
};
|
||||
|
||||
struct BlockDescriptor
|
||||
{
|
||||
uint32_t parentId; ///< This will differ from id if this descriptor was created from runtime named block
|
||||
uint32_t id;
|
||||
int lineNumber;
|
||||
uint32_t argbColor;
|
||||
uint8_t blockType;
|
||||
uint8_t status;
|
||||
std::string blockName;
|
||||
std::string fileName;
|
||||
};
|
||||
|
||||
} //namespace reader
|
||||
|
||||
} //namespace profiler
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_SOCKET_H
|
||||
#define EASY_PROFILER_SOCKET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
// Unix
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netdb.h>
|
||||
# include <stdio.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <netinet/in.h> //for android-build
|
||||
|
||||
#else
|
||||
|
||||
// Windows
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include <ws2tcpip.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
#endif
|
||||
|
||||
class PROFILER_API EasySocket EASY_FINAL
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef SOCKET socket_t;
|
||||
#else
|
||||
typedef int socket_t;
|
||||
#endif
|
||||
|
||||
enum class ConnectionState : int8_t
|
||||
{
|
||||
Disconnected = -1,
|
||||
Unknown,
|
||||
Connected,
|
||||
Connecting
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
socket_t m_socket = 0;
|
||||
socket_t m_replySocket = 0;
|
||||
int m_wsaret = -1;
|
||||
|
||||
struct hostent* m_server = nullptr;
|
||||
struct sockaddr_in m_serverAddress;
|
||||
|
||||
ConnectionState m_state = ConnectionState::Unknown;
|
||||
|
||||
public:
|
||||
|
||||
EasySocket();
|
||||
~EasySocket();
|
||||
|
||||
void setReceiveTimeout(int milliseconds);
|
||||
|
||||
int send(const void* buf, size_t nbyte);
|
||||
int receive(void* buf, size_t nbyte);
|
||||
int listen(int count = 5);
|
||||
int accept();
|
||||
int bind(uint16_t portno);
|
||||
|
||||
bool setAddress(const char* serv, uint16_t port);
|
||||
int connect();
|
||||
|
||||
void flush();
|
||||
void init();
|
||||
|
||||
ConnectionState state() const;
|
||||
bool isDisconnected() const;
|
||||
bool isConnected() const;
|
||||
|
||||
private:
|
||||
|
||||
void checkResult(int result);
|
||||
bool checkSocket(socket_t s) const;
|
||||
void setBlocking(socket_t s, bool blocking);
|
||||
|
||||
}; // end of class EasySocket.
|
||||
|
||||
#endif // EASY_PROFILER_SOCKET_H
|
||||
@@ -0,0 +1,911 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_H
|
||||
#define EASY_PROFILER_H
|
||||
|
||||
#include <easy/details/profiler_public_types.h>
|
||||
|
||||
#define MAX_DYNAMIC_BLOCK_NAME_SIZE_ESTIMATED MAX_BLOCK_DATA_SIZE
|
||||
|
||||
#if defined ( __clang__ )
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
#endif
|
||||
|
||||
//
|
||||
// USING_EASY_PROFILER is defined in details/profiler_in_use.h
|
||||
// if defined BUILD_WITH_EASY_PROFILER and not defined DISABLE_EASY_PROFILER
|
||||
//
|
||||
|
||||
//
|
||||
// BUILD_WITH_EASY_PROFILER is defined in CMakeLists.txt if your project is linked to easy_profiler.
|
||||
//
|
||||
|
||||
//
|
||||
// DISABLE_EASY_PROFILER may be defined manually in source-file before #include <easy/profiler.h>
|
||||
// to disable profiler for certain source-file or project.
|
||||
//
|
||||
|
||||
#ifdef USING_EASY_PROFILER
|
||||
|
||||
// EasyProfiler core API:
|
||||
|
||||
/** Macro for beginning of a scoped block with custom name and color.
|
||||
|
||||
\code
|
||||
#include <easy/profiler.h>
|
||||
void foo()
|
||||
{
|
||||
// some code ...
|
||||
|
||||
EASY_BLOCK("Check something", profiler::OFF); // Disabled block (There is possibility to enable this block later via GUI)
|
||||
if(something){
|
||||
EASY_BLOCK("Calling bar()"); // Block with default color
|
||||
bar();
|
||||
}
|
||||
else{
|
||||
EASY_BLOCK("Calling baz()", profiler::colors::Red); // Red block
|
||||
baz();
|
||||
}
|
||||
EASY_END_BLOCK; // End of "Check something" block (Even if "Check something" is disabled, this EASY_END_BLOCK will not end any other block).
|
||||
|
||||
EASY_BLOCK("Some another block", profiler::colors::Blue, profiler::ON_WITHOUT_CHILDREN); // Block with Blue color without
|
||||
// some another code...
|
||||
EASY_BLOCK("Calculate sum"); // This block will not be profiled because it's parent is ON_WITHOUT_CHILDREN
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
sum += i;
|
||||
EASY_END_BLOCK; // End of "Calculate sum" block
|
||||
}
|
||||
\endcode
|
||||
|
||||
Block will be automatically completed by destructor.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_BLOCK(name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(::profiler::extract_enable_flag(__VA_ARGS__),\
|
||||
EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name), __FILE__, __LINE__, ::profiler::BlockType::Block, ::profiler::extract_color(__VA_ARGS__),\
|
||||
::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
|
||||
::profiler::Block EASY_UNIQUE_BLOCK(__LINE__)(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));\
|
||||
::profiler::beginBlock(EASY_UNIQUE_BLOCK(__LINE__));
|
||||
|
||||
/** Macro for beginning of a non-scoped block with custom name and color.
|
||||
|
||||
You must end such block manually with EASY_END_BLOCK.
|
||||
|
||||
\code
|
||||
#include <easy/profiler.h>
|
||||
void foo() {
|
||||
EASY_NONSCOPED_BLOCK("Callback"); // Begin block which would not be finished when function returns.
|
||||
|
||||
// some code ...
|
||||
}
|
||||
|
||||
void bar() {
|
||||
// some another code...
|
||||
|
||||
EASY_END_BLOCK; // This, as always, ends last opened block. You have to take care about blocks order by yourself.
|
||||
}
|
||||
|
||||
void baz() {
|
||||
foo(); // non-scoped block begins here
|
||||
|
||||
// some code...
|
||||
|
||||
bar(); // non-scoped block ends here
|
||||
}
|
||||
\endcode
|
||||
|
||||
Block will be automatically completed by destructor.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
#define EASY_NONSCOPED_BLOCK(name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(::profiler::extract_enable_flag(__VA_ARGS__),\
|
||||
EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name), __FILE__, __LINE__, ::profiler::BlockType::Block, ::profiler::extract_color(__VA_ARGS__),\
|
||||
::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
|
||||
::profiler::beginNonScopedBlock(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));
|
||||
|
||||
/** Macro for beginning of a block with function name and custom color.
|
||||
|
||||
\code
|
||||
#include <easy/profiler.h>
|
||||
void foo(){
|
||||
EASY_FUNCTION(); // Block with name="foo" and default color
|
||||
//some code...
|
||||
}
|
||||
|
||||
void bar(){
|
||||
EASY_FUNCTION(profiler::colors::Green); // Green block with name="bar"
|
||||
//some code...
|
||||
}
|
||||
|
||||
void baz(){
|
||||
EASY_FUNCTION(profiler::FORCE_ON); // Force enabled block with name="baz" and default color (This block will be profiled even if it's parent is OFF_RECURSIVE)
|
||||
// som code...
|
||||
}
|
||||
\endcode
|
||||
|
||||
Name of the block automatically created with function name.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_FUNCTION(...) EASY_BLOCK(EASY_FUNC_NAME, ## __VA_ARGS__)
|
||||
|
||||
/** Macro for completion of last opened block explicitly.
|
||||
|
||||
\code
|
||||
#include <easy/profiler.h>
|
||||
int foo()
|
||||
{
|
||||
// some code ...
|
||||
|
||||
int sum = 0;
|
||||
EASY_BLOCK("Calculating sum");
|
||||
for (int i = 0; i < 10; ++i){
|
||||
sum += i;
|
||||
}
|
||||
EASY_END_BLOCK;
|
||||
|
||||
// some antoher code here ...
|
||||
|
||||
return sum;
|
||||
}
|
||||
\endcode
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_END_BLOCK ::profiler::endBlock();
|
||||
|
||||
/** Macro for creating event marker with custom name and color.
|
||||
|
||||
Event marker is a block with zero duration and special type.
|
||||
|
||||
\warning Event marker ends immediately and calling EASY_END_BLOCK after EASY_EVENT
|
||||
will end previously opened EASY_BLOCK or EASY_FUNCTION.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_EVENT(name, ...)\
|
||||
EASY_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(\
|
||||
::profiler::extract_enable_flag(__VA_ARGS__), EASY_UNIQUE_LINE_ID, EASY_COMPILETIME_NAME(name),\
|
||||
__FILE__, __LINE__, ::profiler::BlockType::Event, ::profiler::extract_color(__VA_ARGS__),\
|
||||
::std::is_base_of<::profiler::ForceConstStr, decltype(name)>::value));\
|
||||
::profiler::storeEvent(EASY_UNIQUE_DESC(__LINE__), EASY_RUNTIME_NAME(name));
|
||||
|
||||
/** Macro for enabling profiler.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_PROFILER_ENABLE ::profiler::setEnabled(true);
|
||||
|
||||
/** Macro for disabling profiler.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_PROFILER_DISABLE ::profiler::setEnabled(false);
|
||||
|
||||
/** Macro for current thread registration.
|
||||
|
||||
\note If this thread has been already registered then nothing happens.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_THREAD(name)\
|
||||
EASY_THREAD_LOCAL static const char* EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = nullptr;\
|
||||
if (!EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__))\
|
||||
EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = ::profiler::registerThread(name);
|
||||
|
||||
/** Macro for current thread registration and creating a thread guard object.
|
||||
|
||||
\note If this thread has been already registered then nothing happens.
|
||||
|
||||
\note Also creates thread guard which marks thread as "expired" on it's destructor
|
||||
and creates "ThreadFinished" profiler event.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_THREAD_SCOPE(name)\
|
||||
static EASY_THREAD_LOCAL const char* EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = nullptr;\
|
||||
::profiler::ThreadGuard EASY_TOKEN_CONCATENATE(unique_profiler_thread_guard, __LINE__);\
|
||||
if (!EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__))\
|
||||
EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = ::profiler::registerThreadScoped(name,\
|
||||
EASY_TOKEN_CONCATENATE(unique_profiler_thread_guard, __LINE__));
|
||||
|
||||
/** Macro for main thread registration.
|
||||
|
||||
This is just for user's comfort. There is no difference for EasyProfiler GUI between different threads.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_MAIN_THREAD EASY_THREAD("Main")
|
||||
|
||||
/** Enable or disable event tracing (context switch events).
|
||||
|
||||
\note Default value is controlled by EASY_OPTION_EVENT_TRACING_ENABLED macro.
|
||||
|
||||
\note Change will take effect on the next call to EASY_PROFILER_ENABLE.
|
||||
|
||||
\sa EASY_PROFILER_ENABLE, EASY_OPTION_EVENT_TRACING_ENABLED
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_SET_EVENT_TRACING_ENABLED(isEnabled) ::profiler::setEventTracingEnabled(isEnabled);
|
||||
|
||||
/** Set event tracing thread priority (low or normal).
|
||||
|
||||
Event tracing with low priority will affect your application performance much more less, but
|
||||
it can be late to gather information about thread/process (thread could be finished to the moment
|
||||
when event tracing thread will be awaken) and you will not see process name and process id
|
||||
information in GUI for such threads. You will still be able to see all context switch events.
|
||||
|
||||
Event tracing with normal priority could gather more information about processes but potentially
|
||||
it could affect performance as it has more work to do. Usually you will not notice any performance
|
||||
breakdown, but if you care about that then you change set event tracing priority level to low.
|
||||
|
||||
\sa EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority) ::profiler::setLowPriorityEventTracing(isLowPriority);
|
||||
|
||||
/** Macro for setting temporary log-file path for Unix event tracing system.
|
||||
|
||||
\note Default value is "/tmp/cs_profiling_info.log".
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_EVENT_TRACING_SET_LOG(filename) ::profiler::setContextSwitchLogFilename(filename);
|
||||
|
||||
/** Macro returning current path to the temporary log-file for Unix event tracing system.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# define EASY_EVENT_TRACING_LOG ::profiler::getContextSwitchLogFilename();
|
||||
|
||||
// EasyProfiler settings:
|
||||
|
||||
/** If != 0 then EasyProfiler will measure time for blocks storage expansion.
|
||||
If 0 then EasyProfiler will be compiled without blocks of code responsible
|
||||
for measuring these events.
|
||||
|
||||
These are "EasyProfiler.ExpandStorage" blocks on a diagram.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_MEASURE_STORAGE_EXPAND
|
||||
# define EASY_OPTION_MEASURE_STORAGE_EXPAND 0
|
||||
# endif
|
||||
|
||||
# if EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
|
||||
/** If true then "EasyProfiler.ExpandStorage" blocks are enabled by default and will be
|
||||
writed to output file or translated over the net.
|
||||
If false then you need to enable these blocks via GUI if you want to see them.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON
|
||||
# define EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON true
|
||||
# endif
|
||||
|
||||
# endif // EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
|
||||
|
||||
/** If true then EasyProfiler event tracing is enabled by default
|
||||
and will be turned on and off when you call profiler::setEnabled().
|
||||
Otherwise, it have to be turned on via GUI and then it will be
|
||||
turned on/off with next calls of profiler::setEnabled().
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_EVENT_TRACING_ENABLED
|
||||
# define EASY_OPTION_EVENT_TRACING_ENABLED true
|
||||
# endif
|
||||
|
||||
/** If true then EasyProfiler.ETW thread (Event tracing for Windows) will have low priority by default.
|
||||
|
||||
\sa EASY_SET_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\note You can always change priority level via GUI or API while profiling session is not launched.
|
||||
You don't need to rebuild or restart your application for that.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
|
||||
# define EASY_OPTION_LOW_PRIORITY_EVENT_TRACING true
|
||||
# endif
|
||||
|
||||
|
||||
/** If != 0 then EasyProfiler will print error messages into stderr.
|
||||
Otherwise, no log messages will be printed.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_LOG_ENABLED
|
||||
# define EASY_OPTION_LOG_ENABLED 0
|
||||
# endif
|
||||
|
||||
/** If != 0 then EasyProfiler will start listening thread immediately on ProfileManager initialization.
|
||||
|
||||
\sa startListen
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
# ifndef EASY_OPTION_START_LISTEN_ON_STARTUP
|
||||
# define EASY_OPTION_START_LISTEN_ON_STARTUP 0
|
||||
# endif
|
||||
|
||||
#else // #ifdef BUILD_WITH_EASY_PROFILER
|
||||
|
||||
# define EASY_BLOCK(...)
|
||||
# define EASY_NONSCOPED_BLOCK(...)
|
||||
# define EASY_FUNCTION(...)
|
||||
# define EASY_END_BLOCK
|
||||
# define EASY_PROFILER_ENABLE
|
||||
# define EASY_PROFILER_DISABLE
|
||||
# define EASY_EVENT(...)
|
||||
# define EASY_THREAD(...)
|
||||
# define EASY_THREAD_SCOPE(...)
|
||||
# define EASY_MAIN_THREAD
|
||||
# define EASY_SET_EVENT_TRACING_ENABLED(isEnabled)
|
||||
# define EASY_SET_LOW_PRIORITY_EVENT_TRACING(isLowPriority)
|
||||
|
||||
# ifndef _WIN32
|
||||
# define EASY_EVENT_TRACING_SET_LOG(filename)
|
||||
# define EASY_EVENT_TRACING_LOG ""
|
||||
# endif
|
||||
|
||||
# ifndef EASY_OPTION_MEASURE_STORAGE_EXPAND
|
||||
# define EASY_OPTION_MEASURE_STORAGE_EXPAND 0
|
||||
# endif
|
||||
|
||||
# ifndef EASY_OPTION_EVENT_TRACING_ENABLED
|
||||
# define EASY_OPTION_EVENT_TRACING_ENABLED false
|
||||
# endif
|
||||
|
||||
# ifndef EASY_OPTION_LOW_PRIORITY_EVENT_TRACING
|
||||
# define EASY_OPTION_LOW_PRIORITY_EVENT_TRACING true
|
||||
# endif
|
||||
|
||||
# ifndef EASY_OPTION_LOG_ENABLED
|
||||
# define EASY_OPTION_LOG_ENABLED 0
|
||||
# endif
|
||||
|
||||
# ifndef EASY_OPTION_START_LISTEN_ON_STARTUP
|
||||
# define EASY_OPTION_START_LISTEN_ON_STARTUP 0
|
||||
# endif
|
||||
|
||||
#endif // #ifndef BUILD_WITH_EASY_PROFILER
|
||||
|
||||
# ifndef EASY_DEFAULT_PORT
|
||||
# define EASY_DEFAULT_PORT 28077
|
||||
# endif
|
||||
|
||||
/** Alias for EASY_PROFILER_ENABLE.
|
||||
|
||||
Added for clarification.
|
||||
|
||||
\sa EASY_PROFILER_ENABLE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
#define EASY_START_CAPTURE EASY_PROFILER_ENABLE
|
||||
|
||||
/** Alias for EASY_PROFILER_DISABLE.
|
||||
|
||||
Added for clarification.
|
||||
|
||||
\sa EASY_PROFILER_DISABLE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
#define EASY_STOP_CAPTURE EASY_PROFILER_DISABLE
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace profiler {
|
||||
|
||||
EASY_CONSTEXPR uint16_t DEFAULT_PORT = EASY_DEFAULT_PORT;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Core API
|
||||
// Note: It is better to use macros defined above than a direct calls to API.
|
||||
// But some API functions does not have macro wrappers...
|
||||
|
||||
#ifdef USING_EASY_PROFILER
|
||||
extern "C" {
|
||||
|
||||
/** Returns current time in ticks.
|
||||
|
||||
You can use it if you want to store block explicitly.
|
||||
|
||||
\retval Current CPU time in ticks.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t now();
|
||||
|
||||
/** Convert ticks to nanoseconds.
|
||||
|
||||
\retval _ticks converted to nanoseconds.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t toNanoseconds(timestamp_t _ticks);
|
||||
|
||||
/** Convert ticks to microseconds.
|
||||
|
||||
\retval _ticks converted to microseconds.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t toMicroseconds(timestamp_t _ticks);
|
||||
|
||||
/** Registers static description of a block.
|
||||
|
||||
It is general information which is common for all such blocks.
|
||||
Includes color, block type (see BlockType), file-name, line-number, compile-time name of a block and enable-flag.
|
||||
|
||||
\note This API function is used by EASY_EVENT, EASY_BLOCK, EASY_FUNCTION macros.
|
||||
There is no need to invoke this function explicitly.
|
||||
|
||||
\retval Pointer to registered block description.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API const BaseBlockDescriptor* registerDescription(EasyBlockStatus _status, const char* _autogenUniqueId, const char* _compiletimeName, const char* _filename, int _line, block_type_t _block_type, color_t _color, bool _copyName = false);
|
||||
|
||||
/** Stores event in the blocks list.
|
||||
|
||||
An event ends instantly and has zero duration.
|
||||
|
||||
\note There is no need to invoke this function explicitly - use EASY_EVENT macro instead.
|
||||
|
||||
\param _desc Reference to the previously registered description.
|
||||
\param _runtimeName Standard zero-terminated string which will be copied to the events buffer.
|
||||
|
||||
\note _runtimeName must be an empty string ("") if you do not want to set name to the event at run-time.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void storeEvent(const BaseBlockDescriptor* _desc, const char* _runtimeName = "");
|
||||
|
||||
/** Stores block explicitly in the blocks list.
|
||||
|
||||
Use this function for additional flexibility if you want to set block duration manually.
|
||||
|
||||
\param _desc Reference to the previously registered description.
|
||||
\param _runtimeName Standard zero-terminated string which will be copied to the events buffer.
|
||||
\param _beginTime begin time of the block
|
||||
\param _endTime end time of the block
|
||||
|
||||
\note _runtimeName must be an empty string ("") if you do not want to set name to the block at run-time.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void storeBlock(const BaseBlockDescriptor* _desc, const char* _runtimeName, timestamp_t _beginTime, timestamp_t _endTime);
|
||||
|
||||
/** Begins scoped block.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void beginBlock(Block& _block);
|
||||
|
||||
/** Begins non-scoped block.
|
||||
|
||||
\param _desc Reference to the previously registered description (see registerDescription).
|
||||
\param _runtimeName Standard zero-terminated string which will be copied to the block buffer when block will end.
|
||||
|
||||
\note There is no need to invoke this function explicitly - use EASY_NONSCOPED_BLOCK macro instead.
|
||||
EASY_NONSCOPED_BLOCK macro could be used for higher flexibility if you have to begin block in one
|
||||
function and end it in another one.
|
||||
|
||||
\note _runtimeName must be an empty string ("") if you do not want to set name to the block at run-time.
|
||||
\note _runtimeName is copied only when block ends so you must ensure it's validity until block end.
|
||||
|
||||
\warning You have to end this block explicitly.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void beginNonScopedBlock(const BaseBlockDescriptor* _desc, const char* _runtimeName = "");
|
||||
|
||||
/** Ends last started block.
|
||||
|
||||
Use this only if you want to finish block explicitly.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void endBlock();
|
||||
|
||||
/** Enable or disable profiler.
|
||||
|
||||
AKA start or stop profiling (capturing blocks).
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setEnabled(bool _isEnable);
|
||||
PROFILER_API bool isEnabled();
|
||||
|
||||
/** Save all gathered blocks into file.
|
||||
|
||||
\note This also disables profiler.
|
||||
|
||||
\retval Number of saved blocks. If 0 then nothing was profiled or an error occurred.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API uint32_t dumpBlocksToFile(const char* _filename);
|
||||
|
||||
/** Register current thread and give it a name.
|
||||
|
||||
Also creates a scoped ThreadGuard which would unregister thread on it's destructor.
|
||||
This helps for memory management while using an old compiler whitout thread_local support.
|
||||
|
||||
\note Only first call of registerThread() for the current thread will have an effect.
|
||||
|
||||
\note Use this function if you want to build your source code with an old compiler (MSVC < 2013, GCC < 4.8, Clang < 3.3).
|
||||
Otherwise there is no need in this function because a thread_local ThreadGuard created inside.
|
||||
|
||||
\retval Registered name of the thread. It may differ from _name if the thread was registered before.
|
||||
|
||||
\sa registerThread, ThreadGuard
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API const char* registerThreadScoped(const char* _name, ThreadGuard&);
|
||||
|
||||
/** Register current thread and give it a name.
|
||||
|
||||
\note Only first call of registerThread() for the current thread will have an effect.
|
||||
|
||||
\retval Registered name of the thread. It may differ from _name if the thread was registered before.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API const char* registerThread(const char* _name);
|
||||
|
||||
/** Enable or disable event tracing.
|
||||
|
||||
\note This change will take an effect on the next call of setEnabled(true);
|
||||
|
||||
\sa setEnabled, EASY_SET_EVENT_TRACING_ENABLED
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setEventTracingEnabled(bool _isEnable);
|
||||
PROFILER_API bool isEventTracingEnabled();
|
||||
|
||||
/** Set event tracing thread priority (low or normal).
|
||||
|
||||
\note This change will take effect on the next call of setEnabled(true);
|
||||
|
||||
\sa setEnabled, EASY_SET_LOW_PRIORITY_EVENT_TRACING
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority);
|
||||
PROFILER_API bool isLowPriorityEventTracing();
|
||||
|
||||
/** Set temporary log-file path for Unix event tracing system.
|
||||
|
||||
\note Default value is "/tmp/cs_profiling_info.log".
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void setContextSwitchLogFilename(const char* _name);
|
||||
|
||||
/** Returns current path to the temporary log-file for Unix event tracing system.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API const char* getContextSwitchLogFilename();
|
||||
|
||||
/** Start listening for network commands.
|
||||
|
||||
Launches a separate listening thread which would listen to the network commands (start, stop, etc.).
|
||||
The listening thread sends all profiled blocks via network after receiving network command 'stop'.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void startListen(uint16_t _port = ::profiler::DEFAULT_PORT);
|
||||
|
||||
/** Stops listening thread.
|
||||
|
||||
\note This would be invoked automatically on application exit.
|
||||
|
||||
\note Does not send any messages to the network, just stops thread.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API void stopListen();
|
||||
|
||||
/** Check if listening thread launched.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API bool isListening();
|
||||
|
||||
/** Returns current major version.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API uint8_t versionMajor();
|
||||
|
||||
/** Returns current minor version.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API uint8_t versionMinor();
|
||||
|
||||
/** Returns current version patch.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API uint16_t versionPatch();
|
||||
|
||||
/** Returns current version in 32-bit integer format.
|
||||
|
||||
\note Format is: 0x MAJ-MAJ MIN-MIN PATCH-PATCH-PATCH-PATCH
|
||||
For example v1.3.0 is: 0x01030000
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API uint32_t version();
|
||||
|
||||
/** Returns current version string.
|
||||
|
||||
Example: "v1.3.0"
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API const char* versionName();
|
||||
|
||||
/** Returns true if current thread has been marked as Main.
|
||||
Otherwise, returns false.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API bool isMainThread();
|
||||
|
||||
/** Returns last frame duration for current thread.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t this_thread_frameTime(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
/** Returns local max of frame duration for current thread.
|
||||
|
||||
Local max is maximum frame duration since last frameTimeLocalMax() call.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t this_thread_frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
/** Returns local average of frame duration for current thread.
|
||||
|
||||
Local average is average frame duration since last frameTimeLocalAvg() call.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t this_thread_frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
/** Returns last frame duration for main thread.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t main_thread_frameTime(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
/** Returns local max of frame duration for main thread.
|
||||
|
||||
Local max is maximum frame duration since last frameTimeLocalMax() call.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t main_thread_frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
/** Returns local average of frame duration for main thread.
|
||||
|
||||
Local average is average frame duration since last frameTimeLocalAvg() call.
|
||||
|
||||
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
PROFILER_API timestamp_t main_thread_frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS);
|
||||
|
||||
}
|
||||
#else
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t now() { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t toNanoseconds(timestamp_t) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t toMicroseconds(timestamp_t) { return 0; }
|
||||
inline const BaseBlockDescriptor* registerDescription(EasyBlockStatus, const char*, const char*, const char*, int, block_type_t, color_t, bool = false)
|
||||
{ return reinterpret_cast<const BaseBlockDescriptor*>(0xbad); }
|
||||
inline void endBlock() { }
|
||||
inline void setEnabled(bool) { }
|
||||
inline EASY_CONSTEXPR_FCN bool isEnabled() { return false; }
|
||||
inline void storeEvent(const BaseBlockDescriptor*, const char* = "") { }
|
||||
inline void storeBlock(const BaseBlockDescriptor*, const char*, timestamp_t, timestamp_t) { }
|
||||
inline void beginBlock(Block&) { }
|
||||
inline void beginNonScopedBlock(const BaseBlockDescriptor*, const char* = "") { }
|
||||
inline uint32_t dumpBlocksToFile(const char*) { return 0; }
|
||||
inline const char* registerThreadScoped(const char*, ThreadGuard&) { return ""; }
|
||||
inline const char* registerThread(const char*) { return ""; }
|
||||
inline void setEventTracingEnabled(bool) { }
|
||||
inline EASY_CONSTEXPR_FCN bool isEventTracingEnabled() { return false; }
|
||||
inline void setLowPriorityEventTracing(bool) { }
|
||||
inline EASY_CONSTEXPR_FCN bool isLowPriorityEventTracing() { return false; }
|
||||
inline void setContextSwitchLogFilename(const char*) { }
|
||||
inline EASY_CONSTEXPR_FCN const char* getContextSwitchLogFilename() { return ""; }
|
||||
inline void startListen(uint16_t = ::profiler::DEFAULT_PORT) { }
|
||||
inline void stopListen() { }
|
||||
inline EASY_CONSTEXPR_FCN bool isListening() { return false; }
|
||||
inline EASY_CONSTEXPR_FCN uint8_t versionMajor() { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN uint8_t versionMinor() { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN uint16_t versionPatch() { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN uint32_t version() { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN const char* versionName() { return "v0.0.0_disabled"; }
|
||||
inline EASY_CONSTEXPR_FCN bool isMainThread() { return false; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t this_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t this_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t this_thread_frameTimeLocalAvg(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t main_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t main_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
inline EASY_CONSTEXPR_FCN timestamp_t main_thread_frameTimeLocalAvg(Duration = ::profiler::MICROSECONDS) { return 0; }
|
||||
#endif
|
||||
|
||||
/** API functions binded to current thread.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
namespace this_thread {
|
||||
|
||||
inline const char* registrate(const char* _name) {
|
||||
return ::profiler::registerThread(_name);
|
||||
}
|
||||
|
||||
inline const char* registrate(const char* _name, ThreadGuard& _threadGuard) {
|
||||
return ::profiler::registerThreadScoped(_name, _threadGuard);
|
||||
}
|
||||
|
||||
inline timestamp_t frameTime(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::this_thread_frameTime(_durationCast);
|
||||
}
|
||||
|
||||
inline timestamp_t frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::this_thread_frameTimeLocalMax(_durationCast);
|
||||
}
|
||||
|
||||
inline timestamp_t frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::this_thread_frameTimeLocalAvg(_durationCast);
|
||||
}
|
||||
|
||||
inline bool isMain() {
|
||||
return ::profiler::isMainThread();
|
||||
}
|
||||
|
||||
} // END of namespace this_thread.
|
||||
|
||||
/** API functions binded to main thread.
|
||||
|
||||
Could be called from any thread.
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
namespace main_thread {
|
||||
|
||||
inline timestamp_t frameTime(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::main_thread_frameTime(_durationCast);
|
||||
}
|
||||
|
||||
inline timestamp_t frameTimeLocalMax(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::main_thread_frameTimeLocalMax(_durationCast);
|
||||
}
|
||||
|
||||
inline timestamp_t frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS) {
|
||||
return ::profiler::main_thread_frameTimeLocalAvg(_durationCast);
|
||||
}
|
||||
|
||||
/** Always returns true.
|
||||
*/
|
||||
inline EASY_CONSTEXPR_FCN bool isMain() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // END of namespace main_thread.
|
||||
|
||||
/** Alias for isEnabled().
|
||||
|
||||
Added for clarification.
|
||||
|
||||
\sa isEnabled
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
EASY_FORCE_INLINE bool isCapturing() { return isEnabled(); }
|
||||
|
||||
/** Alias for EASY_PROFILER_ENABLE.
|
||||
|
||||
Added for clarification.
|
||||
|
||||
\sa EASY_PROFILER_ENABLE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
EASY_FORCE_INLINE void startCapture() { EASY_PROFILER_ENABLE; }
|
||||
|
||||
/** Alias for EASY_PROFILER_DISABLE.
|
||||
|
||||
Added for clarification.
|
||||
|
||||
\sa EASY_PROFILER_DISABLE
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
EASY_FORCE_INLINE void stopCapture() { EASY_PROFILER_DISABLE; }
|
||||
|
||||
/** Alias for now().
|
||||
|
||||
\ingroup profiler
|
||||
*/
|
||||
EASY_FORCE_INLINE timestamp_t currentTime() { return now(); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
#if defined ( __clang__ )
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // EASY_PROFILER_H
|
||||
+422
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_READER_H
|
||||
#define EASY_PROFILER_READER_H
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 median_duration; ///< Median 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)
|
||||
: total_duration(_duration)
|
||||
, median_duration(0)
|
||||
, total_children_duration(0)
|
||||
, min_duration_block(_block_index)
|
||||
, max_duration_block(_block_index)
|
||||
, parent_block(_parent_index)
|
||||
, calls_number(1)
|
||||
{
|
||||
}
|
||||
|
||||
//BlockStatistics() = default;
|
||||
|
||||
inline profiler::timestamp_t average_duration() const
|
||||
{
|
||||
return total_duration / calls_number;
|
||||
}
|
||||
|
||||
}; // END of struct BlockStatistics.
|
||||
#pragma pack(pop)
|
||||
|
||||
extern "C" PROFILER_API void release_stats(BlockStatistics*& _stats);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BlocksTree EASY_FINAL
|
||||
{
|
||||
using This = BlocksTree;
|
||||
|
||||
public:
|
||||
|
||||
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::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;
|
||||
This& operator = (const This&) = delete;
|
||||
|
||||
BlocksTree() EASY_NOEXCEPT
|
||||
: node(nullptr)
|
||||
, per_parent_stats(nullptr)
|
||||
, per_frame_stats(nullptr)
|
||||
, per_thread_stats(nullptr)
|
||||
, depth(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BlocksTree(This&& that) EASY_NOEXCEPT
|
||||
: BlocksTree()
|
||||
{
|
||||
make_move(std::forward<This&&>(that));
|
||||
}
|
||||
|
||||
This& operator = (This&& that) EASY_NOEXCEPT
|
||||
{
|
||||
make_move(std::forward<This&&>(that));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~BlocksTree() EASY_NOEXCEPT
|
||||
{
|
||||
release_stats(per_thread_stats);
|
||||
release_stats(per_parent_stats);
|
||||
release_stats(per_frame_stats);
|
||||
}
|
||||
|
||||
bool operator < (const This& other) const EASY_NOEXCEPT
|
||||
{
|
||||
if (node == nullptr || other.node == nullptr)
|
||||
return false;
|
||||
return node->begin() < other.node->begin();
|
||||
}
|
||||
|
||||
void shrink_to_fit() EASY_NOEXCEPT
|
||||
{
|
||||
//for (auto& child : children)
|
||||
// child.shrink_to_fit();
|
||||
|
||||
// shrink version 1:
|
||||
//children.shrink_to_fit();
|
||||
|
||||
// shrink version 2:
|
||||
//children_t new_children;
|
||||
//new_children.reserve(children.size());
|
||||
//std::move(children.begin(), children.end(), std::back_inserter(new_children));
|
||||
//new_children.swap(children);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void make_move(This&& that) EASY_NOEXCEPT
|
||||
{
|
||||
if (per_thread_stats != that.per_thread_stats)
|
||||
release_stats(per_thread_stats);
|
||||
|
||||
if (per_parent_stats != that.per_parent_stats)
|
||||
release_stats(per_parent_stats);
|
||||
|
||||
if (per_frame_stats != that.per_frame_stats)
|
||||
release_stats(per_frame_stats);
|
||||
|
||||
children = std::move(that.children);
|
||||
node = that.node;
|
||||
per_parent_stats = that.per_parent_stats;
|
||||
per_frame_stats = that.per_frame_stats;
|
||||
per_thread_stats = that.per_thread_stats;
|
||||
depth = that.depth;
|
||||
|
||||
that.node = nullptr;
|
||||
that.per_parent_stats = nullptr;
|
||||
that.per_frame_stats = nullptr;
|
||||
that.per_thread_stats = nullptr;
|
||||
}
|
||||
|
||||
}; // END of class BlocksTree.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Bookmark EASY_FINAL
|
||||
{
|
||||
EASY_STATIC_CONSTEXPR size_t BaseSize = sizeof(profiler::timestamp_t) +
|
||||
sizeof(profiler::color_t) + 1;
|
||||
|
||||
std::string text;
|
||||
profiler::timestamp_t pos;
|
||||
profiler::color_t color;
|
||||
};
|
||||
|
||||
using bookmarks_t = std::vector<Bookmark>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BlocksTreeRoot EASY_FINAL
|
||||
{
|
||||
using This = BlocksTreeRoot;
|
||||
|
||||
public:
|
||||
|
||||
BlocksTree::children_t children; ///< List of children indexes
|
||||
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
|
||||
uint8_t depth; ///< Maximum stack depth (number of levels)
|
||||
|
||||
BlocksTreeRoot(const This&) = delete;
|
||||
This& operator = (const This&) = delete;
|
||||
|
||||
BlocksTreeRoot() EASY_NOEXCEPT
|
||||
: profiled_time(0), wait_time(0), thread_id(0), frames_number(0), blocks_number(0), depth(0)
|
||||
{
|
||||
}
|
||||
|
||||
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))
|
||||
, profiled_time(that.profiled_time)
|
||||
, wait_time(that.wait_time)
|
||||
, thread_id(that.thread_id)
|
||||
, frames_number(that.frames_number)
|
||||
, blocks_number(that.blocks_number)
|
||||
, depth(that.depth)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
profiled_time = that.profiled_time;
|
||||
wait_time = that.wait_time;
|
||||
thread_id = that.thread_id;
|
||||
frames_number = that.frames_number;
|
||||
blocks_number = that.blocks_number;
|
||||
depth = that.depth;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool got_name() const EASY_NOEXCEPT
|
||||
{
|
||||
return !thread_name.empty();
|
||||
}
|
||||
|
||||
inline const char* name() const EASY_NOEXCEPT
|
||||
{
|
||||
return thread_name.c_str();
|
||||
}
|
||||
|
||||
bool operator < (const This& other) const EASY_NOEXCEPT
|
||||
{
|
||||
return thread_id < other.thread_id;
|
||||
}
|
||||
|
||||
}; // END of class BlocksTreeRoot.
|
||||
|
||||
struct BeginEndTime
|
||||
{
|
||||
profiler::timestamp_t beginTime;
|
||||
profiler::timestamp_t endTime;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
uint64_t m_size;
|
||||
char* m_data;
|
||||
|
||||
public:
|
||||
|
||||
SerializedData(const SerializedData&) = delete;
|
||||
SerializedData& operator = (const SerializedData&) = delete;
|
||||
|
||||
SerializedData();
|
||||
|
||||
SerializedData(SerializedData&& that);
|
||||
|
||||
~SerializedData();
|
||||
|
||||
void set(uint64_t _size);
|
||||
|
||||
void extend(uint64_t _size);
|
||||
|
||||
SerializedData& operator = (SerializedData&& that);
|
||||
|
||||
char* operator [] (uint64_t i);
|
||||
|
||||
const char* operator [] (uint64_t i) const;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
uint64_t size() const;
|
||||
|
||||
char* data();
|
||||
|
||||
const char* data() const;
|
||||
|
||||
void clear();
|
||||
|
||||
void swap(SerializedData& other);
|
||||
|
||||
private:
|
||||
|
||||
void set(char* _data, uint64_t _size);
|
||||
|
||||
}; // END of class SerializedData.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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::BeginEndTime& begin_end_time,
|
||||
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::bookmarks_t& bookmarks,
|
||||
uint32_t& descriptors_count,
|
||||
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::BeginEndTime& begin_end_time,
|
||||
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::bookmarks_t& bookmarks,
|
||||
uint32_t& descriptors_count,
|
||||
uint32_t& version,
|
||||
profiler::processid_t& pid,
|
||||
bool gather_statistics,
|
||||
std::ostream& _log);
|
||||
|
||||
PROFILER_API bool readDescriptionsFromStream(std::atomic<int>& progress, std::istream& str,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
std::ostream& _log);
|
||||
|
||||
}
|
||||
|
||||
inline profiler::block_index_t fillTreesFromFile(const char* filename, profiler::BeginEndTime& begin_end_time,
|
||||
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::bookmarks_t& bookmarks,
|
||||
uint32_t& descriptors_count,
|
||||
uint32_t& version,
|
||||
profiler::processid_t& pid,
|
||||
bool gather_statistics,
|
||||
std::ostream& _log)
|
||||
{
|
||||
std::atomic<int> progress(0);
|
||||
return fillTreesFromFile(progress, filename, begin_end_time, serialized_blocks, serialized_descriptors,
|
||||
descriptors, _blocks, threaded_trees, bookmarks, descriptors_count, version, pid,
|
||||
gather_statistics, _log);
|
||||
}
|
||||
|
||||
inline bool readDescriptionsFromStream(std::istream& str,
|
||||
profiler::SerializedData& serialized_descriptors,
|
||||
profiler::descriptors_list_t& descriptors,
|
||||
std::ostream& _log)
|
||||
{
|
||||
std::atomic<int> progress(0);
|
||||
return readDescriptionsFromStream(progress, str, serialized_descriptors, descriptors, _log);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // EASY_PROFILER_READER_H
|
||||
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_SERIALIZED_BLOCK_H
|
||||
#define EASY_PROFILER_SERIALIZED_BLOCK_H
|
||||
|
||||
#include <easy/details/profiler_public_types.h>
|
||||
#include <easy/details/arbitrary_value_public_types.h>
|
||||
|
||||
class CSwitchBlock;
|
||||
|
||||
namespace profiler {
|
||||
|
||||
template <DataType dataType, bool isArray>
|
||||
struct Value;
|
||||
|
||||
template <bool isArray>
|
||||
struct Value<DataType::TypesCount, isArray>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PROFILER_API SerializedBlock EASY_FINAL : public BaseBlockData
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
friend ::ThreadStorage;
|
||||
|
||||
public:
|
||||
|
||||
inline const char* data() const { return reinterpret_cast<const char*>(this); }
|
||||
|
||||
///< Run-time block name is stored right after main BaseBlockData data
|
||||
inline const char* name() const { return data() + sizeof(BaseBlockData); }
|
||||
|
||||
SerializedBlock(const SerializedBlock&) = delete;
|
||||
SerializedBlock& operator = (const SerializedBlock&) = delete;
|
||||
SerializedBlock(SerializedBlock&&) = delete;
|
||||
SerializedBlock& operator = (SerializedBlock&&) = delete;
|
||||
~SerializedBlock() = delete;
|
||||
|
||||
private:
|
||||
|
||||
explicit SerializedBlock(const Block& block, uint16_t name_length);
|
||||
|
||||
}; // END of SerializedBlock.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma pack(push, 1)
|
||||
class PROFILER_API CSwitchEvent : public Event
|
||||
{
|
||||
thread_id_t m_thread_id;
|
||||
|
||||
public:
|
||||
|
||||
CSwitchEvent() = default;
|
||||
CSwitchEvent(const CSwitchEvent&) = default;
|
||||
explicit CSwitchEvent(timestamp_t _begin_time, thread_id_t _tid) EASY_NOEXCEPT;
|
||||
|
||||
inline thread_id_t tid() const EASY_NOEXCEPT { return m_thread_id; }
|
||||
|
||||
}; // END of class CSwitchEvent.
|
||||
#pragma pack(pop)
|
||||
|
||||
class PROFILER_API SerializedCSwitch EASY_FINAL : public CSwitchEvent
|
||||
{
|
||||
friend ::ProfileManager;
|
||||
friend ::ThreadStorage;
|
||||
|
||||
public:
|
||||
|
||||
inline const char* data() const { return reinterpret_cast<const char*>(this); }
|
||||
|
||||
///< Run-time block name is stored right after main CSwitchEvent data
|
||||
inline const char* name() const { return data() + sizeof(CSwitchEvent); }
|
||||
|
||||
SerializedCSwitch(const SerializedCSwitch&) = delete;
|
||||
SerializedCSwitch& operator = (const SerializedCSwitch&) = delete;
|
||||
SerializedCSwitch(SerializedCSwitch&&) = delete;
|
||||
SerializedCSwitch& operator = (SerializedCSwitch&&) = delete;
|
||||
~SerializedCSwitch() = delete;
|
||||
|
||||
private:
|
||||
|
||||
explicit SerializedCSwitch(const CSwitchBlock& block, uint16_t name_length);
|
||||
|
||||
}; // END of SerializedCSwitch.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma pack(push, 1)
|
||||
class PROFILER_API SerializedBlockDescriptor EASY_FINAL : public BaseBlockDescriptor
|
||||
{
|
||||
uint16_t m_nameLength; ///< Length of the name including trailing '\0' sybmol
|
||||
|
||||
public:
|
||||
|
||||
inline const char* data() const {
|
||||
return reinterpret_cast<const char*>(this);
|
||||
}
|
||||
|
||||
///< Name is stored right after m_nameLength
|
||||
inline const char* name() const {
|
||||
static const auto shift = sizeof(BaseBlockDescriptor) + sizeof(decltype(m_nameLength));
|
||||
return data() + shift;
|
||||
}
|
||||
|
||||
///< File name is stored right after the name
|
||||
inline const char* file() const {
|
||||
return name() + m_nameLength;
|
||||
}
|
||||
|
||||
inline void setStatus(EasyBlockStatus _status) EASY_NOEXCEPT {
|
||||
m_status = _status;
|
||||
}
|
||||
|
||||
// Instances of this class can not be created or destroyed directly
|
||||
SerializedBlockDescriptor() = delete;
|
||||
SerializedBlockDescriptor(const SerializedBlockDescriptor&) = delete;
|
||||
SerializedBlockDescriptor& operator = (const SerializedBlockDescriptor&) = delete;
|
||||
SerializedBlockDescriptor(SerializedBlockDescriptor&&) = delete;
|
||||
SerializedBlockDescriptor& operator = (SerializedBlockDescriptor&&) = delete;
|
||||
~SerializedBlockDescriptor() = delete;
|
||||
|
||||
}; // END of SerializedBlockDescriptor.
|
||||
//#pragma pack(pop)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#pragma pack(push, 1)
|
||||
class PROFILER_API ArbitraryValue : protected BaseBlockData
|
||||
{
|
||||
friend ::ThreadStorage;
|
||||
|
||||
protected:
|
||||
|
||||
char m_nameStub; ///< Artificial padding which is used to imitate SerializedBlock::name() == 0 behavior
|
||||
char m_padding; ///< Padding to the bound of 2 bytes
|
||||
uint16_t m_size;
|
||||
DataType m_type;
|
||||
bool m_isArray;
|
||||
vin_t m_value_id;
|
||||
|
||||
explicit ArbitraryValue(timestamp_t _timestamp, vin_t _vin, block_id_t _id,
|
||||
uint16_t _size, DataType _type, bool _isArray)
|
||||
: BaseBlockData(_timestamp, _timestamp, _id)
|
||||
, m_nameStub(0)
|
||||
, m_padding(0)
|
||||
, m_size(_size)
|
||||
, m_type(_type)
|
||||
, m_isArray(_isArray)
|
||||
, m_value_id(_vin)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
using BaseBlockData::id;
|
||||
using Event::begin;
|
||||
|
||||
~ArbitraryValue() = delete;
|
||||
|
||||
const char* data() const {
|
||||
return reinterpret_cast<const char*>(this) + sizeof(ArbitraryValue);
|
||||
}
|
||||
|
||||
uint16_t data_size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
vin_t value_id() const {
|
||||
return m_value_id;
|
||||
}
|
||||
|
||||
DataType type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
bool isArray() const {
|
||||
return m_isArray;
|
||||
}
|
||||
|
||||
template <DataType dataType>
|
||||
const Value<dataType, false>* toValue() const {
|
||||
return m_type == dataType ? static_cast<const Value<dataType, false>*>(this) : nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const Value<StdToDataType<T>::data_type, false>* toValue() const {
|
||||
static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
|
||||
"You should use standard builtin scalar types as profiler::Value type!");
|
||||
return toValue<StdToDataType<T>::data_type>();
|
||||
}
|
||||
|
||||
template <DataType dataType>
|
||||
const Value<dataType, true>* toArray() const {
|
||||
return m_isArray && m_type == dataType ? static_cast<const Value<dataType, true>*>(this) : nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const Value<StdToDataType<T>::data_type, true>* toArray() const {
|
||||
static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
|
||||
"You should use standard builtin scalar types as profiler::Value type!");
|
||||
return toArray<StdToDataType<T>::data_type>();
|
||||
}
|
||||
}; // end of class ArbitraryValue.
|
||||
#pragma pack(pop)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <DataType dataType>
|
||||
struct Value<dataType, false> EASY_FINAL : public ArbitraryValue {
|
||||
using value_type = typename StdType<dataType>::value_type;
|
||||
value_type value() const { return *reinterpret_cast<const value_type*>(data()); }
|
||||
~Value() = delete;
|
||||
};
|
||||
|
||||
|
||||
template <DataType dataType>
|
||||
struct Value<dataType, true> EASY_FINAL : public ArbitraryValue {
|
||||
using value_type = typename StdType<dataType>::value_type;
|
||||
const value_type* value() const { return reinterpret_cast<const value_type*>(data()); }
|
||||
uint16_t size() const { return m_size / sizeof(value_type); }
|
||||
value_type operator [] (int i) const { return value()[i]; }
|
||||
value_type at(int i) const { return value()[i]; }
|
||||
~Value() = delete;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct Value<DataType::String, true> EASY_FINAL : public ArbitraryValue {
|
||||
using value_type = char;
|
||||
const char* value() const { return data(); }
|
||||
uint16_t size() const { return m_size; }
|
||||
char operator [] (int i) const { return data()[i]; }
|
||||
char at(int i) const { return data()[i]; }
|
||||
const char* c_str() const { return data(); }
|
||||
~Value() = delete;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <DataType dataType>
|
||||
using SingleValue = Value<dataType, false>;
|
||||
|
||||
template <DataType dataType>
|
||||
using ArrayValue = Value<dataType, true>;
|
||||
|
||||
using StringValue = Value<DataType::String, true>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // END of namespace profiler.
|
||||
|
||||
#endif // EASY_PROFILER_SERIALIZED_BLOCK_H
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
|
||||
#ifndef EASY_PROFILER_UTILITY_H
|
||||
#define EASY_PROFILER_UTILITY_H
|
||||
|
||||
#include <easy/details/easy_compiler_support.h>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <math.h>
|
||||
|
||||
namespace estd {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template <class T, bool BiggerThanPtr> struct hasher {
|
||||
using type = const T&;
|
||||
EASY_FORCE_INLINE size_t operator () (type value) const { return ::std::hash<T> {}(value); } };
|
||||
|
||||
template <class T> struct hasher<T, false> {
|
||||
using type = T;
|
||||
EASY_FORCE_INLINE size_t operator () (type value) const { return static_cast<size_t>(value); } };
|
||||
}
|
||||
|
||||
template <class T> struct hash EASY_FINAL : public ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))> {
|
||||
using Parent = ::estd::detail::hasher<T, (sizeof(T) > sizeof(void*))>;
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1910
|
||||
// TODO: Try to compile "using Parent::operator();" in MSVC 2017
|
||||
size_t operator () (typename Parent::type value) const { return Parent::operator () (value); }
|
||||
#else
|
||||
using Parent::operator();
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T> struct hash<T*> EASY_FINAL {
|
||||
EASY_FORCE_INLINE size_t operator () (const T* value) const { return reinterpret_cast<size_t>(value); } };
|
||||
|
||||
template <class T> struct hash<const T*> EASY_FINAL {
|
||||
EASY_FORCE_INLINE size_t operator () (const T* value) const { return reinterpret_cast<size_t>(value); } };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T, class Q, class W>
|
||||
inline EASY_CONSTEXPR_FCN Q clamp(T min_value, Q value, W max_value) {
|
||||
return static_cast<Q>(min_value < value ? (value < max_value ? value : max_value) : min_value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
EASY_FORCE_INLINE EASY_CONSTEXPR_FCN T sqr(T value) {
|
||||
return value * value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
EASY_FORCE_INLINE EASY_CONSTEXPR_FCN int sign(T value) { return value < 0 ? -1 : 1; }
|
||||
|
||||
template <class T>
|
||||
inline EASY_CONSTEXPR_FCN T absmin(T a, T b) { return abs(a) < abs(b) ? a : b; }
|
||||
|
||||
template <int N, class T>
|
||||
inline T logn(T value) {
|
||||
EASY_STATIC_CONSTEXPR double div = 1.0 / log2((double)N);
|
||||
return log2(value) * div;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // end of namespace estd.
|
||||
|
||||
#endif // EASY_PROFILER_UTILITY_H
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
Lightweight profiler library for c++
|
||||
Copyright(C) 2016-2019 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_WRITER_H
|
||||
#define EASY_PROFILER_WRITER_H
|
||||
|
||||
#include <easy/reader.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
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,
|
||||
const profiler::bookmarks_t& bookmarks,
|
||||
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,
|
||||
const profiler::bookmarks_t& bookmarks,
|
||||
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 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,
|
||||
const profiler::bookmarks_t& bookmarks,
|
||||
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(0);
|
||||
return writeTreesToFile(progress, filename, serialized_descriptors, descriptors, descriptors_count, trees,
|
||||
bookmarks, 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,
|
||||
const profiler::bookmarks_t& bookmarks,
|
||||
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(0);
|
||||
return writeTreesToStream(progress, str, serialized_descriptors, descriptors, descriptors_count, trees,
|
||||
bookmarks, std::move(block_getter), begin_time, end_time, pid, log);
|
||||
}
|
||||
|
||||
#endif //EASY_PROFILER_WRITER_H
|
||||
Reference in New Issue
Block a user