Add profiling support using easy_profiler
This commit is contained in:
parent
1d0e9b8a07
commit
b6daf43f33
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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%
|
||||
|
156
src/external/easy/easy_compiler_support.h
vendored
Normal file
156
src/external/easy/easy_compiler_support.h
vendored
Normal 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
149
src/external/easy/easy_net.h
vendored
Normal 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
BIN
src/external/easy/easy_profiler.lib
vendored
Normal file
Binary file not shown.
128
src/external/easy/easy_socket.h
vendored
Normal file
128
src/external/easy/easy_socket.h
vendored
Normal 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
933
src/external/easy/profiler.h
vendored
Normal 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
209
src/external/easy/profiler_aux.h
vendored
Normal 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
412
src/external/easy/profiler_colors.h
vendored
Normal 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
416
src/external/easy/reader.h
vendored
Normal 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
112
src/external/easy/serialized_block.h
vendored
Normal 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
|
Loading…
Reference in New Issue
Block a user