Add profiling support using easy_profiler

This commit is contained in:
Doyle Thai 2017-05-19 17:10:04 +10:00
parent 1d0e9b8a07
commit b6daf43f33
14 changed files with 2635 additions and 76 deletions

View File

@ -1038,6 +1038,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
DTRState *state = (DTRState *)memory->context;
if (!memory->isInit)
{
DTR_DEBUG_PROFILE_START();
// NOTE(doyle): Do premultiply ourselves
stbi_set_unpremultiply_on_load(true);
stbi_set_flip_vertically_on_load(true);
@ -1060,6 +1061,8 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
int x = 5;
DqnMemBuffer_EndTempRegion(tmp);
}
DTR_DEBUG_TIMED_FUNCTION();
DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0));
#if 1

View File

@ -2,10 +2,32 @@
#define DTRENDERER_DEBUG_H
#include "dqn.h"
#define DTR_DEBUG 1
#ifdef DTR_DEBUG
#define DTR_DEBUG_RENDER 0
#define DTR_DEBUG_RENDER 0
#define DTR_DEBUG_PROFILING 1
#ifdef DTR_DEBUG_PROFILING
#define BUILD_WITH_EASY_PROFILER 1
#include "external/easy/profiler.h"
#define DTR_DEBUG_PROFILE_START() profiler::startListen()
#define DTR_DEBUG_PROFILE_END() profiler::stopListen()
#define DTR_DEBUG_TIMED_BLOCK(name) EASY_BLOCK(name)
#define DTR_DEBUG_TIMED_NONSCOPED_BLOCK(name) EASY_NONSCOPED_BLOCK(name)
#define DTR_DEBUG_TIMED_END_BLOCK() EASY_END_BLOCK()
#define DTR_DEBUG_TIMED_FUNCTION() EASY_FUNCTION()
#else
#define DTR_DEBUG_PROFILE_START()
#define DTR_DEBUG_PROFILE_END()
#define DTR_DEBUG_TIMED_BLOCK(name)
#define DTR_DEBUG_TIMED_NONSCOPED_BLOCK(name)
#define DTR_DEBUG_TIMED_END_BLOCK()
#define DTR_DEBUG_TIMED_FUNCTION()
#endif
#endif
typedef struct PlatformRenderBuffer PlatformRenderBuffer;

View File

@ -1,4 +1,5 @@
#include "DTRendererRender.h"
#include "DTRendererDebug.h"
#include "DTRendererPlatform.h"
#define STB_RECT_PACK_IMPLEMENTATION
@ -104,6 +105,7 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer, const
if (!renderBuffer) return;
if (x < 0 || x > (renderBuffer->width - 1)) return;
if (y < 0 || y > (renderBuffer->height - 1)) return;
DTR_DEBUG_TIMED_FUNCTION();
u32 *const bitmapPtr = (u32 *)renderBuffer->memory;
const u32 pitchInU32 = (renderBuffer->width * renderBuffer->bytesPerPixel) / 4;
@ -172,6 +174,7 @@ void DTRRender_Text(PlatformRenderBuffer *const renderBuffer,
{
if (!text) return;
if (!font.bitmap || !font.atlas || !renderBuffer) return;
DTR_DEBUG_TIMED_FUNCTION();
if (len == -1) len = Dqn_strlen(text);
@ -249,6 +252,7 @@ FILE_SCOPE void TransformPoints(const DqnV2 origin, DqnV2 *const pList,
const f32 rotation)
{
if (!pList || numP == 0) return;
DTR_DEBUG_TIMED_FUNCTION();
DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation)));
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x);
@ -266,6 +270,8 @@ void DTRRender_Line(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
DqnV2i b, DqnV4 color)
{
if (!renderBuffer) return;
DTR_DEBUG_TIMED_FUNCTION();
color = DTRRender_SRGB1ToLinearSpaceV4(color);
color = PreMultiplyAlpha1(color);
@ -383,6 +389,7 @@ FILE_SCOPE DqnRect GetBoundingBox(const DqnV2 *const pList, const i32 numP)
void DTRRender_Rectangle(PlatformRenderBuffer *const renderBuffer, DqnV2 min, DqnV2 max,
DqnV4 color, const DTRRenderTransform transform)
{
DTR_DEBUG_TIMED_FUNCTION();
////////////////////////////////////////////////////////////////////////////
// Transform vertexes
////////////////////////////////////////////////////////////////////////////
@ -479,6 +486,8 @@ void DTRRender_Rectangle(PlatformRenderBuffer *const renderBuffer, DqnV2 min, Dq
void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1, DqnV2 p2, DqnV2 p3,
DqnV4 color, const DTRRenderTransform transform)
{
DTR_DEBUG_TIMED_FUNCTION();
////////////////////////////////////////////////////////////////////////////
// Transform vertexes
////////////////////////////////////////////////////////////////////////////
@ -705,10 +714,7 @@ void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
const DTRRenderTransform transform, DqnV4 color)
{
if (!bitmap || !bitmap->memory || !renderBuffer) return;
DQN_ASSERT(color.a >= 0 && color.a <= 1.0f);
DQN_ASSERT(color.r >= 0 && color.r <= 1.0f);
DQN_ASSERT(color.g >= 0 && color.g <= 1.0f);
DQN_ASSERT(color.b >= 0 && color.b <= 1.0f);
DTR_DEBUG_TIMED_FUNCTION();
////////////////////////////////////////////////////////////////////////////
// Transform vertexes
@ -722,11 +728,16 @@ void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
const i32 RECT_PLIST_SIZE = DQN_ARRAY_COUNT(rectPoints.pList);
DqnRect bounds = GetBoundingBox(pList, RECT_PLIST_SIZE);
min = bounds.min;
max = bounds.max;
min = bounds.min;
max = bounds.max;
color = DTRRender_SRGB1ToLinearSpaceV4(color);
color = PreMultiplyAlpha1(color);
DQN_ASSERT(color.a >= 0 && color.a <= 1.0f);
DQN_ASSERT(color.r >= 0 && color.r <= 1.0f);
DQN_ASSERT(color.g >= 0 && color.g <= 1.0f);
DQN_ASSERT(color.b >= 0 && color.b <= 1.0f);
////////////////////////////////////////////////////////////////////////////
// Clip drawing space
////////////////////////////////////////////////////////////////////////////
@ -775,6 +786,7 @@ void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
if (bufXYIsInside)
{
DTR_DEBUG_TIMED_BLOCK("DTRRender_Bitmap TexelCalculation");
DqnV2 bufPRelToBasis = DqnV2_2i(bufferX, bufferY) - rectBasis;
f32 u = DqnV2_Dot(bufPRelToBasis, xAxisRelToBasis) * invXAxisLenSq;
@ -804,86 +816,89 @@ void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
i32 texel4X = DQN_MIN((texelX + 1), bitmap->dim.w - 1);
i32 texel4Y = DQN_MIN((texelY + 1), bitmap->dim.h - 1);
u32 texel1 = *(u32 *)(bitmapPtr + ((texel1X * bitmap->bytesPerPixel) + (texel1Y * pitch)));
u32 texel2 = *(u32 *)(bitmapPtr + ((texel2X * bitmap->bytesPerPixel) + (texel2Y * pitch)));
u32 texel3 = *(u32 *)(bitmapPtr + ((texel3X * bitmap->bytesPerPixel) + (texel3Y * pitch)));
u32 texel4 = *(u32 *)(bitmapPtr + ((texel4X * bitmap->bytesPerPixel) + (texel4Y * pitch)));
{
DTR_DEBUG_TIMED_BLOCK("DTRRender_Bitmap TexelBilinearInterpolation");
u32 texel1 = *(u32 *)(bitmapPtr + ((texel1X * bitmap->bytesPerPixel) + (texel1Y * pitch)));
u32 texel2 = *(u32 *)(bitmapPtr + ((texel2X * bitmap->bytesPerPixel) + (texel2Y * pitch)));
u32 texel3 = *(u32 *)(bitmapPtr + ((texel3X * bitmap->bytesPerPixel) + (texel3Y * pitch)));
u32 texel4 = *(u32 *)(bitmapPtr + ((texel4X * bitmap->bytesPerPixel) + (texel4Y * pitch)));
DqnV4 color1;
color1.a = (f32)(texel1 >> 24);
color1.b = (f32)((texel1 >> 16) & 0xFF);
color1.g = (f32)((texel1 >> 8) & 0xFF);
color1.r = (f32)((texel1 >> 0) & 0xFF);
DqnV4 color1;
color1.a = (f32)(texel1 >> 24);
color1.b = (f32)((texel1 >> 16) & 0xFF);
color1.g = (f32)((texel1 >> 8) & 0xFF);
color1.r = (f32)((texel1 >> 0) & 0xFF);
DqnV4 color2;
color2.a = (f32)(texel2 >> 24);
color2.b = (f32)((texel2 >> 16) & 0xFF);
color2.g = (f32)((texel2 >> 8) & 0xFF);
color2.r = (f32)((texel2 >> 0) & 0xFF);
DqnV4 color2;
color2.a = (f32)(texel2 >> 24);
color2.b = (f32)((texel2 >> 16) & 0xFF);
color2.g = (f32)((texel2 >> 8) & 0xFF);
color2.r = (f32)((texel2 >> 0) & 0xFF);
DqnV4 color3;
color3.a = (f32)(texel3 >> 24);
color3.b = (f32)((texel3 >> 16) & 0xFF);
color3.g = (f32)((texel3 >> 8) & 0xFF);
color3.r = (f32)((texel3 >> 0) & 0xFF);
DqnV4 color3;
color3.a = (f32)(texel3 >> 24);
color3.b = (f32)((texel3 >> 16) & 0xFF);
color3.g = (f32)((texel3 >> 8) & 0xFF);
color3.r = (f32)((texel3 >> 0) & 0xFF);
DqnV4 color4;
color4.a = (f32)(texel4 >> 24);
color4.b = (f32)((texel4 >> 16) & 0xFF);
color4.g = (f32)((texel4 >> 8) & 0xFF);
color4.r = (f32)((texel4 >> 0) & 0xFF);
DqnV4 color4;
color4.a = (f32)(texel4 >> 24);
color4.b = (f32)((texel4 >> 16) & 0xFF);
color4.g = (f32)((texel4 >> 8) & 0xFF);
color4.r = (f32)((texel4 >> 0) & 0xFF);
color1 *= DTRRENDER_INV_255;
color2 *= DTRRENDER_INV_255;
color3 *= DTRRENDER_INV_255;
color4 *= DTRRENDER_INV_255;
color1 *= DTRRENDER_INV_255;
color2 *= DTRRENDER_INV_255;
color3 *= DTRRENDER_INV_255;
color4 *= DTRRENDER_INV_255;
color1 = DTRRender_SRGB1ToLinearSpaceV4(color1);
color2 = DTRRender_SRGB1ToLinearSpaceV4(color2);
color3 = DTRRender_SRGB1ToLinearSpaceV4(color3);
color4 = DTRRender_SRGB1ToLinearSpaceV4(color4);
color1 = DTRRender_SRGB1ToLinearSpaceV4(color1);
color2 = DTRRender_SRGB1ToLinearSpaceV4(color2);
color3 = DTRRender_SRGB1ToLinearSpaceV4(color3);
color4 = DTRRender_SRGB1ToLinearSpaceV4(color4);
DqnV4 color12;
color12.a = DqnMath_Lerp(color1.a, texelFractionalX, color2.a);
color12.b = DqnMath_Lerp(color1.b, texelFractionalX, color2.b);
color12.g = DqnMath_Lerp(color1.g, texelFractionalX, color2.g);
color12.r = DqnMath_Lerp(color1.r, texelFractionalX, color2.r);
DqnV4 color12;
color12.a = DqnMath_Lerp(color1.a, texelFractionalX, color2.a);
color12.b = DqnMath_Lerp(color1.b, texelFractionalX, color2.b);
color12.g = DqnMath_Lerp(color1.g, texelFractionalX, color2.g);
color12.r = DqnMath_Lerp(color1.r, texelFractionalX, color2.r);
DqnV4 color34;
color34.a = DqnMath_Lerp(color3.a, texelFractionalX, color4.a);
color34.b = DqnMath_Lerp(color3.b, texelFractionalX, color4.b);
color34.g = DqnMath_Lerp(color3.g, texelFractionalX, color4.g);
color34.r = DqnMath_Lerp(color3.r, texelFractionalX, color4.r);
DqnV4 color34;
color34.a = DqnMath_Lerp(color3.a, texelFractionalX, color4.a);
color34.b = DqnMath_Lerp(color3.b, texelFractionalX, color4.b);
color34.g = DqnMath_Lerp(color3.g, texelFractionalX, color4.g);
color34.r = DqnMath_Lerp(color3.r, texelFractionalX, color4.r);
DqnV4 blend;
blend.a = DqnMath_Lerp(color12.a, texelFractionalY, color34.a);
blend.b = DqnMath_Lerp(color12.b, texelFractionalY, color34.b);
blend.g = DqnMath_Lerp(color12.g, texelFractionalY, color34.g);
blend.r = DqnMath_Lerp(color12.r, texelFractionalY, color34.r);
DqnV4 blend;
blend.a = DqnMath_Lerp(color12.a, texelFractionalY, color34.a);
blend.b = DqnMath_Lerp(color12.b, texelFractionalY, color34.b);
blend.g = DqnMath_Lerp(color12.g, texelFractionalY, color34.g);
blend.r = DqnMath_Lerp(color12.r, texelFractionalY, color34.r);
DQN_ASSERT(blend.a >= 0 && blend.a <= 1.0f);
DQN_ASSERT(blend.r >= 0 && blend.r <= 1.0f);
DQN_ASSERT(blend.g >= 0 && blend.g <= 1.0f);
DQN_ASSERT(blend.b >= 0 && blend.b <= 1.0f);
DQN_ASSERT(blend.a >= 0 && blend.a <= 1.0f);
DQN_ASSERT(blend.r >= 0 && blend.r <= 1.0f);
DQN_ASSERT(blend.g >= 0 && blend.g <= 1.0f);
DQN_ASSERT(blend.b >= 0 && blend.b <= 1.0f);
// TODO(doyle): Color modulation does not work!!! By supplying
// colors [0->1] it'll reduce some of the coverage of a channel
// and once alpha blending is applied that reduced coverage will
// blend with the background and cause the bitmap to go
// transparent when it shouldn't.
blend.a *= color.a;
blend.r *= color.r;
blend.g *= color.g;
blend.b *= color.b;
// TODO(doyle): Color modulation does not work!!! By supplying
// colors [0->1] it'll reduce some of the coverage of a channel
// and once alpha blending is applied that reduced coverage will
// blend with the background and cause the bitmap to go
// transparent when it shouldn't.
blend.a *= color.a;
blend.r *= color.r;
blend.g *= color.g;
blend.b *= color.b;
#if 0
blend.a = DqnMath_Clampf(blend.a, 0.0f, 1.0f);
blend.r = DqnMath_Clampf(blend.r, 0.0f, 1.0f);
blend.g = DqnMath_Clampf(blend.g, 0.0f, 1.0f);
blend.b = DqnMath_Clampf(blend.b, 0.0f, 1.0f);
blend.a = DqnMath_Clampf(blend.a, 0.0f, 1.0f);
blend.r = DqnMath_Clampf(blend.r, 0.0f, 1.0f);
blend.g = DqnMath_Clampf(blend.g, 0.0f, 1.0f);
blend.b = DqnMath_Clampf(blend.b, 0.0f, 1.0f);
#endif
SetPixel(renderBuffer, bufferX, bufferY, blend, ColorSpace_Linear);
SetPixel(renderBuffer, bufferX, bufferY, blend, ColorSpace_Linear);
}
}
}
}

View File

@ -158,6 +158,10 @@ FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath,
(DTR_UpdateFunction *)GetProcAddress(result.dll, "DTR_Update");
if (updateFunction) result.DTR_Update = updateFunction;
}
else
{
DqnWin32_DisplayLastError("LoadLibraryA failed");
}
return result;
}

View File

@ -25,7 +25,7 @@ pushd ..\bin
REM ////////////////////////////////////////////////////////////////////////////
REM Compile Switches
REM ////////////////////////////////////////////////////////////////////////////
REM EHa- disable exception handling (we don't use)
REM EHa- disable exception handling (currently it's on /EHsc since libraries need)
REM GR- disable c runtime type information (we don't use)
REM MD use dynamic runtime library
REM MT use static runtime library, so build and link it into exe
@ -39,7 +39,7 @@ REM wd4100 unused argument parameters
REM wd4201 nonstandard extension used: nameless struct/union
REM wd4189 local variable is initialised but not referenced
REM wd4505 unreferenced local function not used will be removed
set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc /I..\src\external\
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer
@ -61,7 +61,7 @@ REM Compile
REM ////////////////////////////////////////////////////////////////////////////
del *.pdb >NUL 2>NUL
cl %CompileFlags% %Win32Flags% ..\src\Win32DTRenderer.cpp /link %LinkLibraries% %LinkFlags%
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link ..\src\external\easy\easy_profiler.lib /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
popd
set LastError=%ERRORLEVEL%

View File

@ -0,0 +1,156 @@
/************************************************************************
* 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-2017 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>
//#define EASY_CODE_WRAP(Code) Code
#ifdef _WIN32
// Visual Studio and MinGW
# ifdef _BUILD_PROFILER
# define PROFILER_API __declspec(dllexport)
# else
# define PROFILER_API __declspec(dllimport)
# endif
#endif
#if defined (_MSC_VER)
//////////////////////////////////////////////////////////////////////////
// Visual Studio
# define __func__ __FUNCTION__
# 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
# endif
#elif defined (__clang__)
//////////////////////////////////////////////////////////////////////////
// Clang Compiler
# if (__clang_major__ == 3 && __clang_minor__ < 3) || (__clang_major__ < 3)
// There is no support for C++11 thread_local keyword prior to clang 3.3. Use __thread instead.
# define EASY_THREAD_LOCAL __thread
# endif
# if (__clang_major__ == 2 && __clang_minor__ < 9) || (__clang_major__ < 2)
// 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 2.9
# define EASY_FINAL
# endif
#elif defined(__GNUC__)
//////////////////////////////////////////////////////////////////////////
// GNU Compiler
# if (__GNUC__ == 4 && __GNUC_MINOR__ < 8) || (__GNUC__ < 4)
// 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 (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || (__GNUC__ < 4)
// 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 (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || (__GNUC__ < 4)
// There is no support for C++11 final keyword prior to gcc 4.7
# define EASY_FINAL
# endif
#endif
// END // TODO: Add other compilers support
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Default values
#ifndef EASY_THREAD_LOCAL
# define EASY_THREAD_LOCAL thread_local
# define EASY_THREAD_LOCAL_CPP11
#endif
#ifndef EASY_LOCAL_STATIC_PTR
# define EASY_LOCAL_STATIC_PTR(VarType, VarName, VarInitializer) static VarType VarName = VarInitializer
# define EASY_MAGIC_STATIC_CPP11
#endif
#ifndef EASY_FINAL
# define EASY_FINAL final
#endif
#ifndef PROFILER_API
# define PROFILER_API
#endif
//////////////////////////////////////////////////////////////////////////
#endif // EASY_PROFILER_COMPILER_SUPPORT_H

149
src/external/easy/easy_net.h vendored Normal file
View File

@ -0,0 +1,149 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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 <stdint.h>
namespace profiler {
namespace net {
const uint32_t EASY_MESSAGE_SIGN = 20160909;
#pragma pack(push,1)
enum MessageType : uint8_t
{
MESSAGE_TYPE_ZERO = 0,
MESSAGE_TYPE_REQUEST_START_CAPTURE,
MESSAGE_TYPE_REPLY_START_CAPTURING,
MESSAGE_TYPE_REQUEST_STOP_CAPTURE,
MESSAGE_TYPE_REPLY_BLOCKS,
MESSAGE_TYPE_REPLY_BLOCKS_END,
MESSAGE_TYPE_ACCEPTED_CONNECTION,
MESSAGE_TYPE_REQUEST_BLOCKS_DESCRIPTION,
MESSAGE_TYPE_REPLY_BLOCKS_DESCRIPTION,
MESSAGE_TYPE_REPLY_BLOCKS_DESCRIPTION_END,
MESSAGE_TYPE_EDIT_BLOCK_STATUS,
MESSAGE_TYPE_EVENT_TRACING_STATUS,
MESSAGE_TYPE_EVENT_TRACING_PRIORITY,
MESSAGE_TYPE_CHECK_CONNECTION,
MESSAGE_TYPE_REQUEST_MAIN_FRAME_TIME_MAX_AVG_US,
MESSAGE_TYPE_REPLY_MAIN_FRAME_TIME_MAX_AVG_US,
};
struct Message
{
uint32_t magic_number = EASY_MESSAGE_SIGN;
MessageType type = MESSAGE_TYPE_ZERO;
bool isEasyNetMessage() const
{
return EASY_MESSAGE_SIGN == magic_number;
}
Message() = default;
Message(MessageType _t):type(_t){}
};
struct DataMessage : public Message {
uint32_t size = 0; // bytes
DataMessage(MessageType _t = MESSAGE_TYPE_REPLY_BLOCKS) : Message(_t) {}
DataMessage(uint32_t _s, MessageType _t = MESSAGE_TYPE_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;
BlockStatusMessage(uint32_t _id, uint8_t _status) : Message(MESSAGE_TYPE_EDIT_BLOCK_STATUS), id(_id), status(_status) { }
private:
BlockStatusMessage() = delete;
};
struct EasyProfilerStatus : public Message
{
bool isProfilerEnabled;
bool isEventTracingEnabled;
bool isLowPriorityEventTracing;
EasyProfilerStatus(bool _enabled, bool _ETenabled, bool _ETlowp)
: Message(MESSAGE_TYPE_ACCEPTED_CONNECTION)
, isProfilerEnabled(_enabled)
, isEventTracingEnabled(_ETenabled)
, isLowPriorityEventTracing(_ETlowp)
{
}
private:
EasyProfilerStatus() = delete;
};
struct BoolMessage : public Message {
bool flag = false;
BoolMessage(MessageType _t, bool _flag = false) : Message(_t), flag(_flag) { }
BoolMessage() = default;
};
struct TimestampMessage : public Message {
uint32_t maxValue = 0;
uint32_t avgValue = 0;
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

BIN
src/external/easy/easy_profiler.lib vendored Normal file

Binary file not shown.

128
src/external/easy/easy_socket.h vendored Normal file
View File

@ -0,0 +1,128 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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________SOCKET_________H
#define EASY________SOCKET_________H
#include <stdint.h>
#include <easy/profiler.h>
#ifndef _WIN32
#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
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#endif
class PROFILER_API EasySocket
{
public:
#ifdef _WIN32
typedef SOCKET socket_t;
#else
typedef int socket_t;
#endif
enum ConnectionState
{
CONNECTION_STATE_UNKNOWN,
CONNECTION_STATE_SUCCESS,
CONNECTION_STATE_DISCONNECTED,
CONNECTION_STATE_IN_PROGRESS
};
private:
void checkResult(int result);
bool checkSocket(socket_t s) const;
static int _close(socket_t s);
void setBlocking(socket_t s, bool blocking);
socket_t m_socket = 0;
socket_t m_replySocket = 0;
int wsaret = -1;
struct hostent * server;
struct sockaddr_in serv_addr;
ConnectionState m_state = CONNECTION_STATE_UNKNOWN;
public:
EasySocket();
~EasySocket();
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();
void setState(ConnectionState state){m_state=state;}
ConnectionState state() const{return m_state;}
bool isDisconnected() const
{
return m_state == CONNECTION_STATE_UNKNOWN ||
m_state == CONNECTION_STATE_DISCONNECTED;
}
};
#endif // EASY________SOCKET_________H

933
src/external/easy/profiler.h vendored Normal file
View File

@ -0,0 +1,933 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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/profiler_aux.h>
#if defined ( __clang__ )
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
//
// 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
// 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::BLOCK_TYPE_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::BLOCK_TYPE_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_LOCAL_STATIC_PTR(const ::profiler::BaseBlockDescriptor*, EASY_UNIQUE_DESC(__LINE__), ::profiler::registerDescription(::profiler::extract_enable_flag(__VA_ARGS__),\
EASY_UNIQUE_LINE_ID, __func__, __FILE__, __LINE__, ::profiler::BLOCK_TYPE_BLOCK, ::profiler::extract_color(__VA_ARGS__), false));\
::profiler::Block EASY_UNIQUE_BLOCK(__LINE__)(EASY_UNIQUE_DESC(__LINE__), "");\
::profiler::beginBlock(EASY_UNIQUE_BLOCK(__LINE__)); // this is to avoid compiler warning about unused variable
/** 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 immidiately 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::BLOCK_TYPE_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__) = 0;\
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)\
EASY_THREAD_LOCAL static const char* EASY_TOKEN_CONCATENATE(unique_profiler_thread_name, __LINE__) = 0;\
::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 immidiately 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
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class NonscopedBlock;
class ProfileManager;
struct ThreadStorage;
namespace profiler {
//////////////////////////////////////////////////////////////////////
// Core types
const uint16_t DEFAULT_PORT = EASY_DEFAULT_PORT;
typedef uint64_t timestamp_t;
typedef uint32_t thread_id_t;
typedef uint32_t block_id_t;
enum BlockType : uint8_t
{
BLOCK_TYPE_EVENT = 0,
BLOCK_TYPE_BLOCK,
BLOCK_TYPES_NUMBER
};
typedef BlockType block_type_t;
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)
int 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
BaseBlockDescriptor(block_id_t _id, EasyBlockStatus _status, int _line, block_type_t _block_type, color_t _color);
public:
inline block_id_t id() const { return m_id; }
inline int line() const { return m_line; }
inline color_t color() const { return m_color; }
inline block_type_t type() const { return m_type; }
inline EasyBlockStatus status() const { return m_status; }
}; // END of class BaseBlockDescriptor.
//***********************************************
class PROFILER_API BaseBlockData
{
friend ::ProfileManager;
protected:
timestamp_t m_begin;
timestamp_t m_end;
block_id_t m_id;
public:
BaseBlockData(const BaseBlockData&) = default;
BaseBlockData(timestamp_t _begin_time, block_id_t _id);
BaseBlockData(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _id);
inline timestamp_t begin() const { return m_begin; }
inline timestamp_t end() const { return m_end; }
inline block_id_t id() const { return m_id; }
inline timestamp_t duration() const { return m_end - m_begin; }
inline void setId(block_id_t _id) { m_id = _id; }
private:
BaseBlockData() = delete;
}; // 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);
void finish();
void finish(timestamp_t _time);
inline bool finished() const { return m_end >= m_begin; }
inline EasyBlockStatus status() const { return m_status; }
inline void setStatus(EasyBlockStatus _status) { m_status = _status; }
public:
Block(Block&& that);
Block(const BaseBlockDescriptor* _desc, const char* _runtimeName, bool _scoped = true);
Block(timestamp_t _begin_time, block_id_t _id, const char* _runtimeName);
Block(timestamp_t _begin_time, timestamp_t _end_time, block_id_t _id, const char* _runtimeName);
~Block();
inline const char* name() const { return m_name; }
private:
Block(const Block&) = delete;
Block& operator = (const Block&) = delete;
}; // END of class Block.
//***********************************************
class PROFILER_API ThreadGuard EASY_FINAL {
friend ::ProfileManager;
thread_id_t m_id = 0;
public:
~ThreadGuard();
}; // END of class ThreadGuard.
//////////////////////////////////////////////////////////////////////
// Core API
// Note: it is better to use macros defined above than a direct calls to API.
#ifdef BUILD_WITH_EASY_PROFILER
extern "C" {
/** Returns current time in ticks.
You can use it if you want to store block explicitly.
\ingroup profiler
*/
PROFILER_API timestamp_t currentTime();
/** Convert ticks to nanoseconds.
\ingroup profiler
*/
PROFILER_API timestamp_t toNanoseconds(timestamp_t _ticks);
/** Convert ticks 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.
\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.
\ingroup profiler
*/
PROFILER_API void setEnabled(bool _isEnable);
PROFILER_API bool isEnabled();
/** Save all gathered blocks into file.
\note This also disables profiler.
\ingroup profiler
*/
PROFILER_API uint32_t dumpBlocksToFile(const char* _filename);
/** Register current thread and give it a name.
\note Only first call of registerThread() for the current thread will have an effect.
\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.
\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();
PROFILER_API void startListen(uint16_t _port = ::profiler::DEFAULT_PORT);
PROFILER_API void stopListen();
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.
\ingroup profiler
*/
PROFILER_API uint32_t version();
/** Returns current version in 32-bit integer format.
\ingroup profiler
*/
PROFILER_API const char* versionName();
/** Returns true if current thread has been marked as Main.
Otherwise, returns false.
*/
PROFILER_API bool isMainThread();
/** Returns last frame duration for current thread.
\param _durationCast desired duration units (could be cpu-ticks or microseconds)
*/
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)
*/
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)
*/
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)
*/
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)
*/
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)
*/
PROFILER_API timestamp_t main_thread_frameTimeLocalAvg(Duration _durationCast = ::profiler::MICROSECONDS);
}
#else
inline timestamp_t currentTime() { return 0; }
inline timestamp_t toNanoseconds(timestamp_t) { return 0; }
inline 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 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 bool isEventTracingEnabled() { return false; }
inline void setLowPriorityEventTracing(bool) { }
inline bool isLowPriorityEventTracing() { return false; }
inline void setContextSwitchLogFilename(const char*) { }
inline const char* getContextSwitchLogFilename() { return ""; }
inline void startListen(uint16_t = ::profiler::DEFAULT_PORT) { }
inline void stopListen() { }
inline bool isListening() { return false; }
inline uint8_t versionMajor() { return 0; }
inline uint8_t versionMinor() { return 0; }
inline uint16_t versionPatch() { return 0; }
inline uint32_t version() { return 0; }
inline const char* versionName() { return "v0.0.0_disabled"; }
inline bool isMainThread() { return false; }
inline timestamp_t this_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
inline timestamp_t this_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
inline timestamp_t this_thread_frameTimeLocalAvg(Duration = ::profiler::MICROSECONDS) { return 0; }
inline timestamp_t main_thread_frameTime(Duration = ::profiler::MICROSECONDS) { return 0; }
inline timestamp_t main_thread_frameTimeLocalMax(Duration = ::profiler::MICROSECONDS) { return 0; }
inline 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 bool isMain() {
return true;
}
} // END of namespace main_thread.
//////////////////////////////////////////////////////////////////////
} // END of namespace profiler.
#if defined ( __clang__ )
# pragma clang diagnostic pop
#endif
#endif // EASY_PROFILER_H

209
src/external/easy/profiler_aux.h vendored Normal file
View File

@ -0,0 +1,209 @@
/************************************************************************
* 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-2017 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/easy_compiler_support.h>
#include <easy/profiler_colors.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.
};
struct passthrough_hash EASY_FINAL {
template <class T> inline size_t operator () (T _value) const {
return static_cast<size_t>(_value);
}
};
}
//////////////////////////////////////////////////////////////////////////
#include <type_traits>
#include <string>
# 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 BUILD_WITH_EASY_PROFILER
namespace profiler {
template <const bool> struct NameSwitch;
class ForceConstStr EASY_FINAL {
friend NameSwitch<true>;
friend NameSwitch<false>;
const char* c_str;
ForceConstStr() = delete;
ForceConstStr(const ForceConstStr&) = delete;
ForceConstStr(ForceConstStr&&) = delete;
ForceConstStr& operator = (const ForceConstStr&) = delete;
ForceConstStr& operator = (ForceConstStr&&) = delete;
public:
ForceConstStr(const char* _str) : c_str(_str) {}
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 const char* runtime_name(const ForceConstStr&) { return ""; }
template <class T>
static const char* compiletime_name(const T&, const char* autoGeneratedName) { return autoGeneratedName; }
static const char* compiletime_name(const char*, const char* autoGeneratedName) { return autoGeneratedName; }
static const char* compiletime_name(const ForceConstStr& name, const char*) { return name.c_str; }
};
template <> struct NameSwitch<true> EASY_FINAL {
static const char* runtime_name(const char*) { return ""; }
static const char* runtime_name(const ::std::string& name) { return name.c_str(); }
static const char* runtime_name(const ForceConstStr&) { return ""; }
template <class T>
static const char* compiletime_name(const T&, const char* autoGeneratedName) { return autoGeneratedName; }
static const char* compiletime_name(const char* name, const char*) { return name; }
static const char* compiletime_name(const ForceConstStr& name, const char*) { return name.c_str; }
};
//***********************************************
inline color_t extract_color() {
return ::profiler::colors::Default;
}
template <class ... TArgs>
inline color_t extract_color(::profiler::EasyBlockStatus, TArgs...) {
return ::profiler::colors::Default;
}
template <class ... TArgs>
inline color_t extract_color(color_t _color, TArgs...) {
return _color;
}
template <class T, class ... TArgs>
inline color_t extract_color(T, color_t _color, TArgs...) {
return _color;
}
template <class ... TArgs>
inline color_t extract_color(TArgs...) {
static_assert(sizeof...(TArgs) < 2, "No profiler::color_t in arguments list for EASY_BLOCK(name, ...)!");
return ::profiler::colors::Default;
}
//***********************************************
inline EasyBlockStatus extract_enable_flag() {
return ::profiler::ON;
}
template <class T, class ... TArgs>
inline EasyBlockStatus extract_enable_flag(T, ::profiler::EasyBlockStatus _flag, TArgs...) {
return _flag;
}
template <class ... TArgs>
inline EasyBlockStatus extract_enable_flag(::profiler::EasyBlockStatus _flag, TArgs...) {
return _flag;
}
template <class ... TArgs>
inline EasyBlockStatus extract_enable_flag(TArgs...) {
static_assert(sizeof...(TArgs) < 2, "No EasyBlockStatus in arguments list for EASY_BLOCK(name, ...)!");
return ::profiler::ON;
}
//***********************************************
} // 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 // BUILD_WITH_EASY_PROFILER
//////////////////////////////////////////////////////////////////////////
#endif // EASY_PROFILER_AUX_H

412
src/external/easy/profiler_colors.h vendored Normal file
View File

@ -0,0 +1,412 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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 <stdint.h>
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
namespace profiler {
typedef uint32_t color_t; // Standard four-byte ARGB color format
namespace colors {
///< Change alpha for color. Only 8 major bytes (0xff000000) used from alpha.
inline color_t modify_alpha32(color_t _color, color_t _alpha) {
return (_alpha & 0xff000000) | (_color & 0x00ffffff);
}
///< Change alpha for color.
inline 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 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
const color_t Red50 = 0xffffebee;
const color_t Red100 = 0xffffcdd2;
const color_t Red200 = 0xffef9a9a;
const color_t Red300 = 0xffe57373;
const color_t Red400 = 0xffef5350;
const color_t Red500 = 0xfff44336;
const color_t Red600 = 0xffe53935;
const color_t Red700 = 0xffd32f2f;
const color_t Red800 = 0xffc62828;
const color_t Red900 = 0xffb71c1c;
const color_t RedA100 = 0xffff8a80;
const color_t RedA200 = 0xffff5252;
const color_t RedA400 = 0xffff1744;
const color_t RedA700 = 0xffd50000;
const color_t Pink50 = 0xfffce4ec;
const color_t Pink100 = 0xfff8bbd0;
const color_t Pink200 = 0xfff48fb1;
const color_t Pink300 = 0xfff06292;
const color_t Pink400 = 0xffec407a;
const color_t Pink500 = 0xffe91e63;
const color_t Pink600 = 0xffd81b60;
const color_t Pink700 = 0xffc2185b;
const color_t Pink800 = 0xffad1457;
const color_t Pink900 = 0xff880e4f;
const color_t PinkA100 = 0xffff80ab;
const color_t PinkA200 = 0xffff4081;
const color_t PinkA400 = 0xfff50057;
const color_t PinkA700 = 0xffc51162;
const color_t Purple50 = 0xfff3e5f5;
const color_t Purple100 = 0xffe1bee7;
const color_t Purple200 = 0xffce93d8;
const color_t Purple300 = 0xffba68c8;
const color_t Purple400 = 0xffab47bc;
const color_t Purple500 = 0xff9c27b0;
const color_t Purple600 = 0xff8e24aa;
const color_t Purple700 = 0xff7b1fa2;
const color_t Purple800 = 0xff6a1b9a;
const color_t Purple900 = 0xff4a148c;
const color_t PurpleA100 = 0xffea80fc;
const color_t PurpleA200 = 0xffe040fb;
const color_t PurpleA400 = 0xffd500f9;
const color_t PurpleA700 = 0xffaa00ff;
const color_t DeepPurple50 = 0xffede7f6;
const color_t DeepPurple100 = 0xffd1c4e9;
const color_t DeepPurple200 = 0xffb39ddb;
const color_t DeepPurple300 = 0xff9575cd;
const color_t DeepPurple400 = 0xff7e57c2;
const color_t DeepPurple500 = 0xff673ab7;
const color_t DeepPurple600 = 0xff5e35b1;
const color_t DeepPurple700 = 0xff512da8;
const color_t DeepPurple800 = 0xff4527a0;
const color_t DeepPurple900 = 0xff311b92;
const color_t DeepPurpleA100 = 0xffb388ff;
const color_t DeepPurpleA200 = 0xff7c4dff;
const color_t DeepPurpleA400 = 0xff651fff;
const color_t DeepPurpleA700 = 0xff6200ea;
const color_t Indigo50 = 0xffe8eaf6;
const color_t Indigo100 = 0xffc5cae9;
const color_t Indigo200 = 0xff9fa8da;
const color_t Indigo300 = 0xff7986cb;
const color_t Indigo400 = 0xff5c6bc0;
const color_t Indigo500 = 0xff3f51b5;
const color_t Indigo600 = 0xff3949ab;
const color_t Indigo700 = 0xff303f9f;
const color_t Indigo800 = 0xff283593;
const color_t Indigo900 = 0xff1a237e;
const color_t IndigoA100 = 0xff8c9eff;
const color_t IndigoA200 = 0xff536dfe;
const color_t IndigoA400 = 0xff3d5afe;
const color_t IndigoA700 = 0xff304ffe;
const color_t Blue50 = 0xffe3f2fd;
const color_t Blue100 = 0xffbbdefb;
const color_t Blue200 = 0xff90caf9;
const color_t Blue300 = 0xff64b5f6;
const color_t Blue400 = 0xff42a5f5;
const color_t Blue500 = 0xff2196f3;
const color_t Blue600 = 0xff1e88e5;
const color_t Blue700 = 0xff1976d2;
const color_t Blue800 = 0xff1565c0;
const color_t Blue900 = 0xff0d47a1;
const color_t BlueA100 = 0xff82b1ff;
const color_t BlueA200 = 0xff448aff;
const color_t BlueA400 = 0xff2979ff;
const color_t BlueA700 = 0xff2962ff;
const color_t LightBlue50 = 0xffe1f5fe;
const color_t LightBlue100 = 0xffb3e5fc;
const color_t LightBlue200 = 0xff81d4fa;
const color_t LightBlue300 = 0xff4fc3f7;
const color_t LightBlue400 = 0xff29b6f6;
const color_t LightBlue500 = 0xff03a9f4;
const color_t LightBlue600 = 0xff039be5;
const color_t LightBlue700 = 0xff0288d1;
const color_t LightBlue800 = 0xff0277bd;
const color_t LightBlue900 = 0xff01579b;
const color_t LightBlueA100 = 0xff80d8ff;
const color_t LightBlueA200 = 0xff40c4ff;
const color_t LightBlueA400 = 0xff00b0ff;
const color_t LightBlueA700 = 0xff0091ea;
const color_t Cyan50 = 0xffe0f7fa;
const color_t Cyan100 = 0xffb2ebf2;
const color_t Cyan200 = 0xff80deea;
const color_t Cyan300 = 0xff4dd0e1;
const color_t Cyan400 = 0xff26c6da;
const color_t Cyan500 = 0xff00bcd4;
const color_t Cyan600 = 0xff00acc1;
const color_t Cyan700 = 0xff0097a7;
const color_t Cyan800 = 0xff00838f;
const color_t Cyan900 = 0xff006064;
const color_t CyanA100 = 0xff84ffff;
const color_t CyanA200 = 0xff18ffff;
const color_t CyanA400 = 0xff00e5ff;
const color_t CyanA700 = 0xff00b8d4;
const color_t Teal50 = 0xffe0f2f1;
const color_t Teal100 = 0xffb2dfdb;
const color_t Teal200 = 0xff80cbc4;
const color_t Teal300 = 0xff4db6ac;
const color_t Teal400 = 0xff26a69a;
const color_t Teal500 = 0xff009688;
const color_t Teal600 = 0xff00897b;
const color_t Teal700 = 0xff00796b;
const color_t Teal800 = 0xff00695c;
const color_t Teal900 = 0xff004d40;
const color_t TealA100 = 0xffa7ffeb;
const color_t TealA200 = 0xff64ffda;
const color_t TealA400 = 0xff1de9b6;
const color_t TealA700 = 0xff00bfa5;
const color_t Green50 = 0xffe8f5e9;
const color_t Green100 = 0xffc8e6c9;
const color_t Green200 = 0xffa5d6a7;
const color_t Green300 = 0xff81c784;
const color_t Green400 = 0xff66bb6a;
const color_t Green500 = 0xff4caf50;
const color_t Green600 = 0xff43a047;
const color_t Green700 = 0xff388e3c;
const color_t Green800 = 0xff2e7d32;
const color_t Green900 = 0xff1b5e20;
const color_t GreenA100 = 0xffb9f6ca;
const color_t GreenA200 = 0xff69f0ae;
const color_t GreenA400 = 0xff00e676;
const color_t GreenA700 = 0xff00c853;
const color_t LightGreen50 = 0xfff1f8e9;
const color_t LightGreen100 = 0xffdcedc8;
const color_t LightGreen200 = 0xffc5e1a5;
const color_t LightGreen300 = 0xffaed581;
const color_t LightGreen400 = 0xff9ccc65;
const color_t LightGreen500 = 0xff8bc34a;
const color_t LightGreen600 = 0xff7cb342;
const color_t LightGreen700 = 0xff689f38;
const color_t LightGreen800 = 0xff558b2f;
const color_t LightGreen900 = 0xff33691e;
const color_t LightGreenA100 = 0xffccff90;
const color_t LightGreenA200 = 0xffb2ff59;
const color_t LightGreenA400 = 0xff76ff03;
const color_t LightGreenA700 = 0xff64dd17;
const color_t Lime50 = 0xfff9ebe7;
const color_t Lime100 = 0xfff0f4c3;
const color_t Lime200 = 0xffe6ee9c;
const color_t Lime300 = 0xffdce775;
const color_t Lime400 = 0xffd4e157;
const color_t Lime500 = 0xffcddc39;
const color_t Lime600 = 0xffc0ca33;
const color_t Lime700 = 0xffafb42b;
const color_t Lime800 = 0xff9e9d24;
const color_t Lime900 = 0xff827717;
const color_t LimeA100 = 0xfff4ff81;
const color_t LimeA200 = 0xffeeff41;
const color_t LimeA400 = 0xffc6ff00;
const color_t LimeA700 = 0xffaeea00;
const color_t Yellow50 = 0xfffffde7;
const color_t Yellow100 = 0xfffff9c4;
const color_t Yellow200 = 0xfffff59d;
const color_t Yellow300 = 0xfffff176;
const color_t Yellow400 = 0xffffee58;
const color_t Yellow500 = 0xffffeb3b;
const color_t Yellow600 = 0xfffdd835;
const color_t Yellow700 = 0xfffbc02d;
const color_t Yellow800 = 0xfff9a825;
const color_t Yellow900 = 0xfff57f17;
const color_t YellowA100 = 0xffffff8d;
const color_t YellowA200 = 0xffffff00;
const color_t YellowA400 = 0xffffea00;
const color_t YellowA700 = 0xffffd600;
const color_t Amber50 = 0xfffff8e1;
const color_t Amber100 = 0xffffecb3;
const color_t Amber200 = 0xffffe082;
const color_t Amber300 = 0xffffd54f;
const color_t Amber400 = 0xffffca28;
const color_t Amber500 = 0xffffc107;
const color_t Amber600 = 0xffffb300;
const color_t Amber700 = 0xffffa000;
const color_t Amber800 = 0xffff8f00;
const color_t Amber900 = 0xffff6f00;
const color_t AmberA100 = 0xffffe57f;
const color_t AmberA200 = 0xffffd740;
const color_t AmberA400 = 0xffffc400;
const color_t AmberA700 = 0xffffab00;
const color_t Orange50 = 0xfffff3e0;
const color_t Orange100 = 0xffffe0b2;
const color_t Orange200 = 0xffffcc80;
const color_t Orange300 = 0xffffb74d;
const color_t Orange400 = 0xffffa726;
const color_t Orange500 = 0xffff9800;
const color_t Orange600 = 0xfffb8c00;
const color_t Orange700 = 0xfff57c00;
const color_t Orange800 = 0xffef6c00;
const color_t Orange900 = 0xffe65100;
const color_t OrangeA100 = 0xffffd180;
const color_t OrangeA200 = 0xffffab40;
const color_t OrangeA400 = 0xffff9100;
const color_t OrangeA700 = 0xffff6d00;
const color_t DeepOrange50 = 0xfffbe9e7;
const color_t DeepOrange100 = 0xffffccbc;
const color_t DeepOrange200 = 0xffffab91;
const color_t DeepOrange300 = 0xffff8a65;
const color_t DeepOrange400 = 0xffff7043;
const color_t DeepOrange500 = 0xffff5722;
const color_t DeepOrange600 = 0xfff4511e;
const color_t DeepOrange700 = 0xffe64a19;
const color_t DeepOrange800 = 0xffd84315;
const color_t DeepOrange900 = 0xffbf360c;
const color_t DeepOrangeA100 = 0xffff9e80;
const color_t DeepOrangeA200 = 0xffff6e40;
const color_t DeepOrangeA400 = 0xffff3d00;
const color_t DeepOrangeA700 = 0xffdd2c00;
const color_t Brown50 = 0xffefebe9;
const color_t Brown100 = 0xffd7ccc8;
const color_t Brown200 = 0xffbcaaa4;
const color_t Brown300 = 0xffa1887f;
const color_t Brown400 = 0xff8d6e63;
const color_t Brown500 = 0xff795548;
const color_t Brown600 = 0xff6d4c41;
const color_t Brown700 = 0xff5d4037;
const color_t Brown800 = 0xff4e342e;
const color_t Brown900 = 0xff3e2723;
const color_t Grey50 = 0xfffafafa;
const color_t Grey100 = 0xfff5f5f5;
const color_t Grey200 = 0xffeeeeee;
const color_t Grey300 = 0xffe0e0e0;
const color_t Grey400 = 0xffbdbdbd;
const color_t Grey500 = 0xff9e9e9e;
const color_t Grey600 = 0xff757575;
const color_t Grey700 = 0xff616161;
const color_t Grey800 = 0xff424242;
const color_t Grey900 = 0xff212121;
const color_t BlueGrey50 = 0xffeceff1;
const color_t BlueGrey100 = 0xffcfd8dc;
const color_t BlueGrey200 = 0xffb0bec5;
const color_t BlueGrey300 = 0xff90a4ae;
const color_t BlueGrey400 = 0xff78909c;
const color_t BlueGrey500 = 0xff607d8b;
const color_t BlueGrey600 = 0xff546e7a;
const color_t BlueGrey700 = 0xff455a64;
const color_t BlueGrey800 = 0xff37474f;
const color_t BlueGrey900 = 0xff263238;
const color_t Black = 0xff000000;
const color_t White = 0xffffffff;
const color_t Null = 0x00000000;
const color_t Red = Red500;
const color_t DarkRed = Red900;
const color_t Coral = Red200;
const color_t RichRed = 0xffff0000;
const color_t Pink = Pink500;
const color_t Rose = PinkA100;
const color_t Purple = Purple500;
const color_t Magenta = PurpleA200;
const color_t DarkMagenta = PurpleA700;
const color_t DeepPurple = DeepPurple500;
const color_t Indigo = Indigo500;
const color_t Blue = Blue500;
const color_t DarkBlue = Blue900;
const color_t RichBlue = 0xff0000ff;
const color_t LightBlue = LightBlue500;
const color_t SkyBlue = LightBlueA100;
const color_t Navy = LightBlue800;
const color_t Cyan = Cyan500;
const color_t DarkCyan = Cyan900;
const color_t Teal = Teal500;
const color_t DarkTeal = Teal900;
const color_t Green = Green500;
const color_t DarkGreen = Green900;
const color_t RichGreen = 0xff00ff00;
const color_t LightGreen = LightGreen500;
const color_t Mint = LightGreen900;
const color_t Lime = Lime500;
const color_t Olive = Lime900;
const color_t Yellow = Yellow500;
const color_t RichYellow = YellowA200;
const color_t Amber = Amber500;
const color_t Gold = Amber300;
const color_t PaleGold = AmberA100;
const color_t Orange = Orange500;
const color_t Skin = Orange100;
const color_t DeepOrange = DeepOrange500;
const color_t Brick = DeepOrange900;
const color_t Brown = Brown500;
const color_t DarkBrown = Brown900;
const color_t CreamWhite = Orange50;
const color_t Wheat = Amber100;
const color_t Grey = Grey500;
const color_t Dark = Grey900;
const color_t Silver = Grey300;
const color_t BlueGrey = BlueGrey500;
const color_t Default = Wheat;
#else
const 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

416
src/external/easy/reader.h vendored Normal file
View File

@ -0,0 +1,416 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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 PROFILER_READER____H
#define PROFILER_READER____H
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <unordered_map>
#include <vector>
#include <string>
#include <atomic>
#include <easy/profiler.h>
#include <easy/serialized_block.h>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace profiler {
typedef uint32_t calls_number_t;
typedef uint32_t block_index_t;
#pragma pack(push, 1)
struct BlockStatistics EASY_FINAL
{
::profiler::timestamp_t total_duration; ///< Total duration of all block calls
::profiler::timestamp_t total_children_duration; ///< Total duration of all children of all block calls
::profiler::block_index_t min_duration_block; ///< Will be used in GUI to jump to the block with min duration
::profiler::block_index_t max_duration_block; ///< Will be used in GUI to jump to the block with max duration
::profiler::block_index_t parent_block; ///< Index of block which is "parent" for "per_parent_stats" or "frame" for "per_frame_stats" or thread-id for "per_thread_stats"
::profiler::calls_number_t calls_number; ///< Block calls number
explicit BlockStatistics(::profiler::timestamp_t _duration, ::profiler::block_index_t _block_index, ::profiler::block_index_t _parent_index)
: total_duration(_duration)
, total_children_duration(0)
, min_duration_block(_block_index)
, 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
{
typedef BlocksTree This;
public:
typedef ::std::vector<This> blocks_t;
typedef ::std::vector<::profiler::block_index_t> children_t;
children_t children; ///< List of children blocks. May be empty.
::profiler::SerializedBlock* node; ///< Pointer to serilized data (type, name, begin, end etc.)
::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()
: node(nullptr)
, per_parent_stats(nullptr)
, per_frame_stats(nullptr)
, per_thread_stats(nullptr)
, depth(0)
{
}
BlocksTree(This&& that) : BlocksTree()
{
make_move(::std::forward<This&&>(that));
}
This& operator = (This&& that)
{
make_move(::std::forward<This&&>(that));
return *this;
}
~BlocksTree()
{
release_stats(per_thread_stats);
release_stats(per_parent_stats);
release_stats(per_frame_stats);
}
bool operator < (const This& other) const
{
if (!node || !other.node)
return false;
return node->begin() < other.node->begin();
}
void shrink_to_fit()
{
//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:
BlocksTree(const This&) = delete;
This& operator = (const This&) = delete;
void make_move(This&& that)
{
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.
//////////////////////////////////////////////////////////////////////////
class BlocksTreeRoot EASY_FINAL
{
typedef BlocksTreeRoot This;
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 blocks_number; ///< Total blocks number including their children
uint8_t depth; ///< Maximum stack depth (number of levels)
BlocksTreeRoot() : profiled_time(0), wait_time(0), thread_id(0), blocks_number(0), depth(0)
{
}
BlocksTreeRoot(This&& that)
: 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)
, blocks_number(that.blocks_number)
, depth(that.depth)
{
}
This& operator = (This&& that)
{
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;
blocks_number = that.blocks_number;
depth = that.depth;
return *this;
}
inline bool got_name() const
{
return !thread_name.empty();
}
inline const char* name() const
{
return thread_name.c_str();
}
bool operator < (const This& other) const
{
return thread_id < other.thread_id;
}
private:
BlocksTreeRoot(const This&) = delete;
This& operator = (const This&) = delete;
}; // END of class BlocksTreeRoot.
typedef ::profiler::BlocksTree::blocks_t blocks_t;
typedef ::std::unordered_map<::profiler::thread_id_t, ::profiler::BlocksTreeRoot, ::profiler::passthrough_hash> thread_blocks_tree_t;
//////////////////////////////////////////////////////////////////////////
class PROFILER_API SerializedData EASY_FINAL
{
char* m_data;
size_t m_size;
public:
SerializedData() : m_data(nullptr), m_size(0)
{
}
SerializedData(SerializedData&& that) : m_data(that.m_data), m_size(that.m_size)
{
that.m_data = nullptr;
that.m_size = 0;
}
~SerializedData()
{
clear();
}
void set(uint64_t _size);
void extend(uint64_t _size);
SerializedData& operator = (SerializedData&& that)
{
set(that.m_data, that.m_size);
that.m_data = nullptr;
that.m_size = 0;
return *this;
}
char* operator [] (uint64_t i)
{
return m_data + i;
}
const char* operator [] (uint64_t i) const
{
return m_data + i;
}
bool empty() const
{
return m_size == 0;
}
uint64_t size() const
{
return m_size;
}
char* data()
{
return m_data;
}
const char* data() const
{
return m_data;
}
void clear()
{
set(nullptr, 0);
}
void swap(SerializedData& other)
{
char* d = other.m_data;
uint64_t sz = other.m_size;
other.m_data = m_data;
other.m_size = m_size;
m_data = d;
m_size = sz;
}
private:
void set(char* _data, uint64_t _size);
SerializedData(const SerializedData&) = delete;
SerializedData& operator = (const SerializedData&) = delete;
}; // END of class SerializedData.
//////////////////////////////////////////////////////////////////////////
typedef ::std::vector<SerializedBlockDescriptor*> descriptors_list_t;
} // END of namespace profiler.
extern "C" {
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics,
::std::stringstream& _log);
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics,
::std::stringstream& _log);
PROFILER_API bool readDescriptionsFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors,
::std::stringstream& _log);
}
inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics,
::std::stringstream& _log)
{
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, total_descriptors_number, gather_statistics, _log);
}
inline bool readDescriptionsFromStream(::std::stringstream& str,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors,
::std::stringstream& _log)
{
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
return readDescriptionsFromStream(progress, str, serialized_descriptors, descriptors, _log);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // PROFILER_READER____H

112
src/external/easy/serialized_block.h vendored Normal file
View File

@ -0,0 +1,112 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2017 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/profiler.h>
namespace profiler {
//////////////////////////////////////////////////////////////////////////
class PROFILER_API SerializedBlock EASY_FINAL : public BaseBlockData
{
friend ::ProfileManager;
friend ::ThreadStorage;
public:
inline const char* data() const { return reinterpret_cast<const char*>(this); }
inline const char* name() const { return data() + sizeof(BaseBlockData); }
private:
SerializedBlock(const ::profiler::Block& block, uint16_t name_length);
SerializedBlock(const SerializedBlock&) = delete;
SerializedBlock& operator = (const SerializedBlock&) = delete;
~SerializedBlock() = delete;
}; // END of SerializedBlock.
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
class PROFILER_API SerializedBlockDescriptor EASY_FINAL : public BaseBlockDescriptor
{
uint16_t m_nameLength;
public:
inline const char* data() const {
return reinterpret_cast<const char*>(this);
}
inline const char* name() const {
static const auto shift = sizeof(BaseBlockDescriptor) + sizeof(decltype(m_nameLength));
return data() + shift;
}
inline const char* file() const {
return name() + m_nameLength;
}
inline void setStatus(EasyBlockStatus _status)
{
m_status = _status;
}
private:
SerializedBlockDescriptor(const SerializedBlockDescriptor&) = delete;
SerializedBlockDescriptor& operator = (const SerializedBlockDescriptor&) = delete;
~SerializedBlockDescriptor() = delete;
}; // END of SerializedBlockDescriptor.
#pragma pack(pop)
//////////////////////////////////////////////////////////////////////////
} // END of namespace profiler.
#endif // EASY_PROFILER_SERIALIZED_BLOCK_H