Integration of the Shiny lightweight intrusive profiler.

This commit is contained in:
bubnikv 2016-09-14 11:43:38 +02:00
parent 4c67230436
commit b1575b4dcb
21 changed files with 2730 additions and 0 deletions

View File

@ -116,6 +116,26 @@ src/slic3r/GUI/3DScene.cpp
src/slic3r/GUI/3DScene.hpp src/slic3r/GUI/3DScene.hpp
src/slic3r/GUI/GUI.cpp src/slic3r/GUI/GUI.cpp
src/slic3r/GUI/GUI.hpp src/slic3r/GUI/GUI.hpp
src/Shiny/Shiny.h
src/Shiny/ShinyData.h
src/Shiny/ShinyManager.h
src/Shiny/ShinyNodePool.h
src/Shiny/ShinyOutput.h
src/Shiny/ShinyTools.h
src/Shiny/ShinyZone.h
src/Shiny/ShinyConfig.h
src/Shiny/ShinyMacros.h
src/Shiny/ShinyNode.h
src/Shiny/ShinyNodeState.h
src/Shiny/ShinyPrereqs.h
src/Shiny/ShinyVersion.h
src/Shiny/ShinyManager.c
src/Shiny/ShinyNode.c
src/Shiny/ShinyNodePool.c
src/Shiny/ShinyNodeState.c
src/Shiny/ShinyOutput.c
src/Shiny/ShinyTools.c
src/Shiny/ShinyZone.c
src/xsinit.h src/xsinit.h
t/01_trianglemesh.t t/01_trianglemesh.t
t/03_point.t t/03_point.t

33
xs/src/Shiny/Shiny.h Normal file
View File

@ -0,0 +1,33 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_H
#define SHINY_H
/*---------------------------------------------------------------------------*/
#include "ShinyMacros.h"
#include "ShinyManager.h"
#endif /* SHINY_H */

View File

@ -0,0 +1,69 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_CONFIG_H
#define SHINY_CONFIG_H
/*---------------------------------------------------------------------------*/
/* SHINY_IS_COMPILED is the master on or off swith at compile time. Define it to TRUE or FALSE before including header Shiny.h or inside ShinyConfig.h. Default is TRUE.
*/
#if defined(SLIC3R_PROFILE) && defined(WIN32)
#define SHINY_IS_COMPILED TRUE
#endif
#define SHINY_STATIC_LINK TRUE
/* if SHINY_LOOKUP_RATE is defined to TRUE then Shiny will record the success of its hash function. This is useful for debugging. Default is FALSE.
*/
#ifndef SHINY_LOOKUP_RATE
// #define SHINY_LOOKUP_RATE FALSE
#endif
/* if SHINY_HAS_ENABLED is defined to TRUE then Shiny can be enabled and disabled at runtime. TODO: bla bla...
*/
#ifndef SHINY_HAS_ENABLED
// #define SHINY_HAS_ENABLED FALSE
#endif
/* TODO:
*/
#define SHINY_OUTPUT_MODE_FLAT 0x1
/* TODO:
*/
#define SHINY_OUTPUT_MODE_TREE 0x2
/* TODO:
*/
#define SHINY_OUTPUT_MODE_BOTH 0x3
/* TODO:
*/
#ifndef SHINY_OUTPUT_MODE
#define SHINY_OUTPUT_MODE SHINY_OUTPUT_MODE_BOTH
#endif
#endif /* SHINY_CONFIG_H */

102
xs/src/Shiny/ShinyData.h Normal file
View File

@ -0,0 +1,102 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_DATA_H
#define SHINY_DATA_H
#include "ShinyPrereqs.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct {
uint32_t entryCount;
shinytick_t selfTicks;
} ShinyLastData;
/*---------------------------------------------------------------------------*/
typedef struct {
shinytick_t cur;
float avg;
} ShinyTickData;
typedef struct {
uint32_t cur;
float avg;
} ShinyCountData;
typedef struct {
ShinyCountData entryCount;
ShinyTickData selfTicks;
ShinyTickData childTicks;
} ShinyData;
SHINY_INLINE shinytick_t ShinyData_totalTicksCur(const ShinyData *self) {
return self->selfTicks.cur + self->childTicks.cur;
}
SHINY_INLINE float ShinyData_totalTicksAvg(const ShinyData *self) {
return self->selfTicks.avg + self->childTicks.avg;
}
SHINY_INLINE void ShinyData_computeAverage(ShinyData *self, float a_damping) {
self->entryCount.avg = self->entryCount.cur +
a_damping * (self->entryCount.avg - self->entryCount.cur);
self->selfTicks.avg = self->selfTicks.cur +
a_damping * (self->selfTicks.avg - self->selfTicks.cur);
self->childTicks.avg = self->childTicks.cur +
a_damping * (self->childTicks.avg - self->childTicks.cur);
}
SHINY_INLINE void ShinyData_copyAverage(ShinyData *self) {
self->entryCount.avg = (float) self->entryCount.cur;
self->selfTicks.avg = (float) self->selfTicks.cur;
self->childTicks.avg = (float) self->childTicks.cur;
}
SHINY_INLINE void ShinyData_clearAll(ShinyData *self) {
self->entryCount.cur = 0;
self->entryCount.avg = 0;
self->selfTicks.cur = 0;
self->selfTicks.avg = 0;
self->childTicks.cur = 0;
self->childTicks.avg = 0;
}
SHINY_INLINE void ShinyData_clearCurrent(ShinyData *self) {
self->entryCount.cur = 0;
self->selfTicks.cur = 0;
self->childTicks.cur = 0;
}
#if __cplusplus
} /* end of extern "C" */
#endif
#endif /* SHINY_DATA_H */

297
xs/src/Shiny/ShinyMacros.h Normal file
View File

@ -0,0 +1,297 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_MACROS_H
#define SHINY_MACROS_H
#include "ShinyManager.h"
#ifdef SHINY_IS_COMPILED
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_UPDATE() \
ShinyManager_update(&Shiny_instance)
#define PROFILE_SET_DAMPING(floatfrom0to1) \
Shiny_instance.damping = (floatfrom0to1);
#define PROFILE_GET_DAMPING() \
(Shiny_instance.damping)
#define PROFILE_OUTPUT(filename) \
ShinyManager_output(&Shiny_instance, (filename))
#define PROFILE_OUTPUT_STREAM(stream) \
ShinyManager_outputToStream(&Shiny_instance, (stream))
#ifdef __cplusplus
#define PROFILE_GET_TREE_STRING() \
ShinyManager_outputTreeToString(&Shiny_instance)
#define PROFILE_GET_FLAT_STRING() \
ShinyManager_outputFlatToString(&Shiny_instance)
#endif /* __cplusplus */
#define PROFILE_DESTROY() \
ShinyManager_destroy(&Shiny_instance)
#define PROFILE_CLEAR() \
ShinyManager_clear(&Shiny_instance)
#define PROFILE_SORT_ZONES() \
ShinyManager_sortZones(&Shiny_instance)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_GET_TOTAL_TICKS_CUR() \
ShinyData_totalTicksCur(&Shiny_instance.rootZone.data)
#define PROFILE_GET_TOTAL_TICKS() \
ShinyData_totalTicksAvg(&Shiny_instance.rootZone.data)
#define PROFILE_GET_PROFILED_TICKS_CUR() \
(Shiny_instance.rootZone.data.selfTicks.cur)
#define PROFILE_GET_PROFILED_TICKS() \
(Shiny_instance.rootZone.data.selfTicks.avg)
#define PROFILE_GET_UNPROFILED_TICKS_CUR() \
(Shiny_instance.rootZone.data.childTicks.cur)
#define PROFILE_GET_UNPROFILED_TICKS() \
(Shiny_instance.rootZone.data.childTicks.avg)
#define PROFILE_GET_SHARED_TOTAL_TICKS_CUR(name) \
ShinyData_totalTicksCur(&(_PROFILE_ID_ZONE_SHARED(name).data))
#define PROFILE_GET_SHARED_TOTAL_TICKS(name) \
ShinyData_totalTicksAvg(&(_PROFILE_ID_ZONE_SHARED(name).data))
#define PROFILE_GET_SHARED_SELF_TICKS_CUR(name) \
(_PROFILE_ID_ZONE_SHARED(name).data.selfTicks.cur)
#define PROFILE_GET_SHARED_SELF_TICKS(name) \
(_PROFILE_ID_ZONE_SHARED(name).data.selfTicks.avg)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_IS_SHARED_SELF_BELOW(name, floatfrom0to1) \
ShinyManager_isZoneSelfTimeBelow( \
&Shiny_instance, _PROFILE_ID_ZONE_SHARED(name), floatfrom0to1)
#define PROFILE_IS_SHARED_TOTAL_BELOW(name, floatfrom0to1) \
ShinyManager_isZoneTotalTimeBelow( \
&Shiny_instance, _PROFILE_ID_ZONE_SHARED(name), floatfrom0to1)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_END() \
ShinyManager_endCurNode(&Shiny_instance)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_BEGIN( name ) \
\
static _PROFILE_ZONE_DEFINE(_PROFILE_ID_ZONE(name), #name); \
_PROFILE_ZONE_BEGIN(_PROFILE_ID_ZONE(name))
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#ifdef __cplusplus
#define PROFILE_BLOCK( name ) \
\
_PROFILE_BLOCK_DEFINE(_PROFILE_ID_BLOCK()); \
PROFILE_BEGIN(name)
#endif /* __cplusplus */
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#ifdef __cplusplus
#define PROFILE_FUNC() \
\
_PROFILE_BLOCK_DEFINE(_PROFILE_ID_BLOCK()); \
static _PROFILE_ZONE_DEFINE(_PROFILE_ID_ZONE_FUNC(), __FUNCTION__); \
_PROFILE_ZONE_BEGIN(_PROFILE_ID_ZONE_FUNC())
#endif /* __cplusplus */
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_CODE( code ) \
\
do { \
static _PROFILE_ZONE_DEFINE(_PROFILE_ID_ZONE_CODE(), #code); \
_PROFILE_ZONE_BEGIN(_PROFILE_ID_ZONE_CODE()); \
{ code; } \
PROFILE_END(); \
} while(0)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_SHARED_EXTERN( name ) \
\
_PROFILE_ZONE_DECLARE(extern, _PROFILE_ID_ZONE_SHARED(name))
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_SHARED_DEFINE( name ) \
\
_PROFILE_ZONE_DEFINE(_PROFILE_ID_ZONE_SHARED(name), #name)
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#define PROFILE_SHARED_BEGIN( name ) \
\
_PROFILE_ZONE_BEGIN(_PROFILE_ID_ZONE_SHARED(name))
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#ifdef __cplusplus
#define PROFILE_SHARED_BLOCK( name ) \
\
_PROFILE_BLOCK_DEFINE(_PROFILE_ID_BLOCK()); \
_PROFILE_ZONE_BEGIN(_PROFILE_ID_ZONE_SHARED(name))
#endif /* __cplusplus */
/*---------------------------------------------------------------------------*/
/* public preprocessors */
#ifdef SHINY_HAS_ENABLED
#define PROFILE_SET_ENABLED( boolean ) \
Shiny_instance.enabled = boolean
#endif
/*---------------------------------------------------------------------------*/
/* internal preprocessors */
#define _PROFILE_ID_ZONE( name ) __ShinyZone_##name
#define _PROFILE_ID_ZONE_FUNC() __ShinyZoneFunc
#define _PROFILE_ID_ZONE_CODE() __ShinyZoneCode
#define _PROFILE_ID_ZONE_SHARED( name ) name##__ShinyZoneShared
#define _PROFILE_ID_BLOCK() __ShinyBlock
/*---------------------------------------------------------------------------*/
/* internal preprocessor */
#define _PROFILE_ZONE_DEFINE( id, string ) \
\
ShinyZone id = { \
NULL, SHINY_ZONE_STATE_HIDDEN, string, \
{ { 0, 0 }, { 0, 0 }, { 0, 0 } } \
}
/*---------------------------------------------------------------------------*/
/* internal preprocessor */
#define _PROFILE_ZONE_DECLARE( prefix, id ) \
\
prefix ShinyZone id
/*---------------------------------------------------------------------------*/
/* internal preprocessor */
#define _PROFILE_BLOCK_DEFINE( id ) \
\
ShinyEndNodeOnDestruction SHINY_UNUSED id
/*---------------------------------------------------------------------------*/
/* internal preprocessor */
#define _PROFILE_ZONE_BEGIN( id ) \
\
do { \
static ShinyNodeCache cache = &_ShinyNode_dummy; \
ShinyManager_lookupAndBeginNode(&Shiny_instance, &cache, &id); \
} while(0)
/*---------------------------------------------------------------------------*/
#else /* #if SHINY_IS_COMPILED == TRUE */
#ifdef __cplusplus
extern "C" {
#endif
SHINY_INLINE ShinyData GetEmptyData() {
ShinyData a = { { 0, 0 }, { 0, 0 }, { 0, 0 } };
return a;
}
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#define PROFILE_UPDATE()
#define PROFILE_SET_DAMPING(x)
#define PROFILE_GET_DAMPING() 0.0f
#define PROFILE_OUTPUT(x)
#define PROFILE_OUTPUT_STREAM(x)
#define PROFILE_CLEAR()
#define PROFILE_GET_TREE_STRING() std::string()
#define PROFILE_GET_FLAT_STRING() std::string()
#define PROFILE_DESTROY()
#define PROFILE_BEGIN(name)
#define PROFILE_BLOCK(name)
#define PROFILE_FUNC()
#define PROFILE_CODE(code) do { code; } while (0)
#define PROFILE_SHARED_GLOBAL(name)
#define PROFILE_SHARED_MEMBER(name)
#define PROFILE_SHARED_DEFINE(name)
#define PROFILE_SHARED_BEGIN(name)
#define PROFILE_SHARED_BLOCK(name)
#define PROFILE_GET_SHARED_DATA(name) ShinyGetEmptyData()
#define PROFILE_GET_ROOT_DATA() ShinyGetEmptyData()
#if SHINY_HAS_ENABLED == TRUE
#define PROFILE_SET_ENABLED(boolean)
#endif
#endif /* SHINY_IS_COMPILED */
#endif /* SHINY_MACROS_H */

446
xs/src/Shiny/ShinyManager.c Normal file
View File

@ -0,0 +1,446 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyManager.h"
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
#define TABLE_SIZE_INIT 256
/*---------------------------------------------------------------------------*/
ShinyManager Shiny_instance = {
#if SHINY_HAS_ENABLED == TRUE
/* enabled = */ false,
#endif
/* _lastTick = */ 0,
/* _curNode = */ &Shiny_instance.rootNode,
/* _tableMask = */ 0,
/* _nodeTable = */ _ShinyManager_dummyNodeTable,
#if SHINY_LOOKUP_RATE == TRUE
/* _lookupCount = */ 0,
/* _lookupSuccessCount = */ 0,
#endif
/* _tableSize = */ 1,
/* nodeCount = */ 1,
/* zoneCount = */ 1,
/* _lastZone = */ &Shiny_instance.rootZone,
/* _lastNodePool = */ NULL,
/* _firstNodePool = */ NULL,
/* rootNode = */ {
/* _last = */ { 0, 0 },
/* zone = */ &Shiny_instance.rootZone,
/* parent = */ &Shiny_instance.rootNode,
/* nextSibling = */ NULL,
/* firstChild = */ NULL,
/* lastChild = */ NULL,
/* childCount = */ 0,
/* entryLevel = */ 0,
/* _cache = */ NULL,
/* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } }
},
/* rootZone = */ {
/* next = */ NULL,
/* _state = */ SHINY_ZONE_STATE_HIDDEN,
/* name = */ "<unprofiled>",
/* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } }
},
/* damping = */ 0.9f,
/* _initialized = */ FALSE,
/* _firstUpdate = */ TRUE
};
ShinyNode* _ShinyManager_dummyNodeTable[] = { NULL };
/*---------------------------------------------------------------------------*/
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# pragma warning (push)
# pragma warning (disable: 4311)
#endif
/* primary hash function */
SHINY_INLINE uint32_t hash_value(void* a_pParent, void* a_pZone) {
// uint32_t a = (uint32_t) a_pParent + (uint32_t) a_pZone;
uint32_t a = *reinterpret_cast<uint32_t*>(&a_pParent) + *reinterpret_cast<uint32_t*>(&a_pZone);
a = (a+0x7ed55d16) + (a<<12);
a = (a^0xc761c23c) ^ (a>>19);
return a;
}
/*
* secondary hash used as index offset: force it to be odd
* so it's relatively prime to the power-of-two table size
*/
SHINY_INLINE uint32_t hash_offset(uint32_t a) {
return ((a << 8) + (a >> 4)) | 1;
}
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# pragma warning (pop)
#endif
/*---------------------------------------------------------------------------*/
void ShinyManager_preLoad(ShinyManager *self) {
if (!self->_initialized) {
_ShinyManager_init(self);
_ShinyManager_createNodeTable(self, TABLE_SIZE_INIT);
_ShinyManager_createNodePool(self, TABLE_SIZE_INIT / 2);
}
}
/*---------------------------------------------------------------------------*/
void ShinyManager_update(ShinyManager *self) {
#if SHINY_HAS_ENABLED == TRUE
if (!enabled) return;
#endif
_ShinyManager_appendTicksToCurNode(self);
ShinyZone_preUpdateChain(&self->rootZone);
if (self->_firstUpdate || self->damping == 0) {
self->_firstUpdate = FALSE;
ShinyNode_updateTreeClean(&self->rootNode);
ShinyZone_updateChainClean(&self->rootZone);
} else {
ShinyNode_updateTree(&self->rootNode, self->damping);
ShinyZone_updateChain(&self->rootZone, self->damping);
}
}
/*---------------------------------------------------------------------------*/
void ShinyManager_updateClean(ShinyManager *self) {
#if SHINY_HAS_ENABLED == TRUE
if (!enabled) return;
#endif
_ShinyManager_appendTicksToCurNode(self);
ShinyZone_preUpdateChain(&self->rootZone);
self->_firstUpdate = FALSE;
ShinyNode_updateTreeClean(&self->rootNode);
ShinyZone_updateChainClean(&self->rootZone);
}
/*---------------------------------------------------------------------------*/
void ShinyManager_clear(ShinyManager *self) {
ShinyManager_destroy(self);
ShinyManager_preLoad(self);
}
/*---------------------------------------------------------------------------*/
void ShinyManager_destroy(ShinyManager *self) {
ShinyManager_destroyNodes(self);
ShinyManager_resetZones(self);
_ShinyManager_uninit(self);
}
/*---------------------------------------------------------------------------*/
ShinyNode* _ShinyManager_lookupNode(ShinyManager *self, ShinyNodeCache *a_cache, ShinyZone *a_zone) {
uint32_t nHash = hash_value(self->_curNode, a_zone);
uint32_t nIndex = nHash & self->_tableMask;
ShinyNode* pNode = self->_nodeTable[nIndex];
_ShinyManager_incLookup(self);
_ShinyManager_incLookupSuccess(self);
if (pNode) {
uint32_t nStep;
if (ShinyNode_isEqual(pNode, self->_curNode, a_zone)) return pNode; /* found it! */
/* hash collision: */
/* compute a secondary hash function for stepping */
nStep = hash_offset(nHash);
for (;;) {
_ShinyManager_incLookup(self);
nIndex = (nIndex + nStep) & self->_tableMask;
pNode = self->_nodeTable[nIndex];
if (!pNode) break; /* found empty slot */
else if (ShinyNode_isEqual(pNode, self->_curNode, a_zone)) return pNode; /* found it! */
}
/* loop is guaranteed to end because the hash table is never full */
}
if (a_zone->_state == SHINY_ZONE_STATE_HIDDEN) { /* zone is not initialized */
ShinyZone_init(a_zone, self->_lastZone);
self->_lastZone = a_zone;
self->zoneCount++;
if (self->_initialized == FALSE) { /* first time init */
_ShinyManager_init(self);
_ShinyManager_createNodeTable(self, TABLE_SIZE_INIT);
_ShinyManager_createNodePool(self, TABLE_SIZE_INIT / 2);
/* initialization has invalidated nIndex
* we must compute nIndex again
*/
return _ShinyManager_createNode(self, a_cache, a_zone);
}
}
/* Althouth nodeCount is not updated
* it includes rootNode so it adds up.
*
* check if we need to grow the table
* we keep it at most 1/2 full to be very fast
*/
if (self->_tableSize < 2 * self->nodeCount) {
_ShinyManager_resizeNodeTable(self, 2 * self->_tableSize);
_ShinyManager_resizeNodePool(self, self->nodeCount - 1);
/* resize has invalidated nIndex
* we must compute nIndex again
*/
return _ShinyManager_createNode(self, a_cache, a_zone);
}
self->nodeCount++;
{
ShinyNode* pNewNode = ShinyNodePool_newItem(self->_lastNodePool);
ShinyNode_init(pNewNode, self->_curNode, a_zone, a_cache);
self->_nodeTable[nIndex] = pNewNode;
return pNewNode;
}
}
/*---------------------------------------------------------------------------*/
void _ShinyManager_insertNode(ShinyManager *self, ShinyNode* a_pNode) {
uint32_t nHash = hash_value(a_pNode->parent, a_pNode->zone);
uint32_t nIndex = nHash & self->_tableMask;
if (self->_nodeTable[nIndex]) {
uint32_t nStep = hash_offset(nHash);
while (self->_nodeTable[nIndex])
nIndex = (nIndex + nStep) & self->_tableMask;
}
self->_nodeTable[nIndex] = a_pNode;
}
/*---------------------------------------------------------------------------*/
ShinyNode* _ShinyManager_createNode(ShinyManager *self, ShinyNodeCache* a_cache, ShinyZone* a_pZone) {
ShinyNode* pNewNode = ShinyNodePool_newItem(self->_lastNodePool);
ShinyNode_init(pNewNode, self->_curNode, a_pZone, a_cache);
self->nodeCount++;
_ShinyManager_insertNode(self, pNewNode);
return pNewNode;
}
/*---------------------------------------------------------------------------*/
void _ShinyManager_createNodePool(ShinyManager *self, uint32_t a_nCount) {
self->_firstNodePool = ShinyNodePool_create(a_nCount);
self->_lastNodePool = self->_firstNodePool;
}
/*---------------------------------------------------------------------------*/
void _ShinyManager_resizeNodePool(ShinyManager *self, uint32_t a_nCount) {
ShinyNodePool* pPool = ShinyNodePool_create(a_nCount);
self->_lastNodePool->nextPool = pPool;
self->_lastNodePool = pPool;
}
/*---------------------------------------------------------------------------*/
void _ShinyManager_createNodeTable(ShinyManager *self, uint32_t a_nCount) {
self->_tableSize = a_nCount;
self->_tableMask = a_nCount - 1;
self->_nodeTable = (ShinyNodeTable*)
malloc(sizeof(ShinyNode) * a_nCount);
memset(self->_nodeTable, 0, a_nCount * sizeof(ShinyNode*));
}
/*---------------------------------------------------------------------------*/
void _ShinyManager_resizeNodeTable(ShinyManager *self, uint32_t a_nCount) {
ShinyNodePool* pPool;
free(self->_nodeTable);
_ShinyManager_createNodeTable(self, a_nCount);
pPool = self->_firstNodePool;
while (pPool) {
ShinyNode *pIter = ShinyNodePool_firstItem(pPool);
while (pIter != pPool->_nextItem)
_ShinyManager_insertNode(self, pIter++);
pPool = pPool->nextPool;
}
}
/*---------------------------------------------------------------------------*/
void ShinyManager_resetZones(ShinyManager *self) {
ShinyZone_resetChain(&self->rootZone);
self->_lastZone = &self->rootZone;
self->zoneCount = 1;
}
/*---------------------------------------------------------------------------*/
void ShinyManager_destroyNodes(ShinyManager *self) {
if (self->_firstNodePool) {
ShinyNodePool_destroy(self->_firstNodePool);
self->_firstNodePool = NULL;
}
if (self->_nodeTable != _ShinyManager_dummyNodeTable) {
free(self->_nodeTable);
self->_nodeTable = _ShinyManager_dummyNodeTable;
self->_tableSize = 1;
self->_tableMask = 0;
}
self->_curNode = &self->rootNode;
self->nodeCount = 1;
_ShinyManager_init(self);
}
/*---------------------------------------------------------------------------*/
const char* ShinyManager_getOutputErrorString(ShinyManager *self) {
if (self->_firstUpdate) return "!!! Profile data must first be updated !!!";
else if (!self->_initialized) return "!!! No profiles where executed !!!";
else return NULL;
}
/*---------------------------------------------------------------------------*/
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# pragma warning (push)
# pragma warning (disable: 4996)
#endif
int ShinyManager_output(ShinyManager *self, const char *a_filename) {
if (!a_filename) {
ShinyManager_outputToStream(self, stdout);
} else {
FILE *file = fopen(a_filename, "w");
if (!file) return FALSE;
ShinyManager_outputToStream(self, file);
fclose(file);
}
return TRUE;
}
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# pragma warning (pop)
#endif
/*---------------------------------------------------------------------------*/
void ShinyManager_outputToStream(ShinyManager *self, FILE *a_stream) {
const char *error = ShinyManager_getOutputErrorString(self);
if (error) {
fwrite(error, 1, strlen(error), a_stream);
fwrite("\n\n", 1, 2, a_stream);
return;
}
#if SHINY_OUTPUT_MODE & SHINY_OUTPUT_MODE_FLAT
ShinyManager_sortZones(self);
{
int size = ShinyPrintZonesSize(self->zoneCount);
char *buffer = (char*) malloc(size);
ShinyPrintZones(buffer, &self->rootZone);
fwrite(buffer, 1, size - 1, a_stream);
fwrite("\n\n", 1, 2, a_stream);
free(buffer);
}
#endif
#if SHINY_OUTPUT_MODE & SHINY_OUTPUT_MODE_TREE
{
int size = ShinyPrintNodesSize(self->nodeCount);
char *buffer = (char*) malloc(size);
ShinyPrintNodes(buffer, &self->rootNode);
fwrite(buffer, 1, size - 1, a_stream);
fwrite("\n\n", 1, 2, a_stream);
free(buffer);
}
#endif
}
#endif /* if SHINY_IS_COMPILED == TRUE */

267
xs/src/Shiny/ShinyManager.h Normal file
View File

@ -0,0 +1,267 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_MANAGER_H
#define SHINY_MANAGER_H
#include "ShinyZone.h"
#include "ShinyNode.h"
#include "ShinyNodePool.h"
#include "ShinyTools.h"
#include "ShinyOutput.h"
#include <stdio.h>
#ifdef SHINY_IS_COMPILED
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct {
#ifdef SHINY_HAS_ENABLED
bool enabled;
#endif
shinytick_t _lastTick;
ShinyNode* _curNode;
uint32_t _tableMask; /* = _tableSize - 1 */
ShinyNodeTable* _nodeTable;
#ifdef SHINY_LOOKUP_RATE
uint64_t _lookupCount;
uint64_t _lookupSuccessCount;
#endif
uint32_t _tableSize;
uint32_t nodeCount;
uint32_t zoneCount;
ShinyZone* _lastZone;
ShinyNodePool* _lastNodePool;
ShinyNodePool* _firstNodePool;
ShinyNode rootNode;
ShinyZone rootZone;
float damping;
int _initialized;
int _firstUpdate;
} ShinyManager;
/*---------------------------------------------------------------------------*/
extern ShinyNode* _ShinyManager_dummyNodeTable[];
extern ShinyManager Shiny_instance;
/*---------------------------------------------------------------------------*/
SHINY_INLINE void _ShinyManager_appendTicksToCurNode(ShinyManager *self) {
shinytick_t curTick;
ShinyGetTicks(&curTick);
ShinyNode_appendTicks(self->_curNode, curTick - self->_lastTick);
self->_lastTick = curTick;
}
SHINY_API ShinyNode* _ShinyManager_lookupNode(ShinyManager *self, ShinyNodeCache* a_cache, ShinyZone* a_zone);
SHINY_API void _ShinyManager_createNodeTable(ShinyManager *self, uint32_t a_count);
SHINY_API void _ShinyManager_resizeNodeTable(ShinyManager *self, uint32_t a_count);
SHINY_API void _ShinyManager_createNodePool(ShinyManager *self, uint32_t a_count);
SHINY_API void _ShinyManager_resizeNodePool(ShinyManager *self, uint32_t a_count);
SHINY_API ShinyNode* _ShinyManager_createNode(ShinyManager *self, ShinyNodeCache* a_cache, ShinyZone* a_pZone);
SHINY_API void _ShinyManager_insertNode(ShinyManager *self, ShinyNode* a_pNode);
SHINY_INLINE void _ShinyManager_init(ShinyManager *self) {
self->_initialized = TRUE;
self->rootNode._last.entryCount = 1;
self->rootNode._last.selfTicks = 0;
ShinyGetTicks(&self->_lastTick);
}
SHINY_INLINE void _ShinyManager_uninit(ShinyManager *self) {
self->_initialized = FALSE;
ShinyNode_clear(&self->rootNode);
self->rootNode.parent = &self->rootNode;
self->rootNode.zone = &self->rootZone;
}
#ifdef SHINY_LOOKUP_RATE
SHINY_INLINE void _ShinyManager_incLookup(ShinyManager *self) { self->_lookupCount++; }
SHINY_INLINE void _ShinyManager_incLookupSuccess(ShinyManager *self) { self->_lookupSuccessCount++; }
SHINY_INLINE float ShinyManager_lookupRate(const ShinyManager *self) { return ((float) self->_lookupSuccessCount) / ((float) self->_lookupCount); }
#else
SHINY_INLINE void _ShinyManager_incLookup(ShinyManager * self) { self = self; }
SHINY_INLINE void _ShinyManager_incLookupSuccess(ShinyManager * self) { self = self; }
SHINY_INLINE float ShinyManager_lookupRate(const ShinyManager * self) { self = self; return -1; }
#endif
SHINY_API void ShinyManager_resetZones(ShinyManager *self);
SHINY_API void ShinyManager_destroyNodes(ShinyManager *self);
SHINY_INLINE float ShinyManager_tableUsage(const ShinyManager *self) {
return ((float) self->nodeCount) / ((float) self->_tableSize);
}
SHINY_INLINE uint32_t ShinyManager_allocMemInBytes(const ShinyManager *self) {
return self->_tableSize * sizeof(ShinyNode*)
+ (self->_firstNodePool)? ShinyNodePool_memoryUsageChain(self->_firstNodePool) : 0;
}
SHINY_INLINE void ShinyManager_beginNode(ShinyManager *self, ShinyNode* a_node) {
ShinyNode_beginEntry(a_node);
_ShinyManager_appendTicksToCurNode(self);
self->_curNode = a_node;
}
SHINY_INLINE void ShinyManager_lookupAndBeginNode(ShinyManager *self, ShinyNodeCache* a_cache, ShinyZone* a_zone) {
#ifdef SHINY_HAS_ENABLED
if (!self->enabled) return;
#endif
if (self->_curNode != (*a_cache)->parent)
*a_cache = _ShinyManager_lookupNode(self, a_cache, a_zone);
ShinyManager_beginNode(self, *a_cache);
}
SHINY_INLINE void ShinyManager_endCurNode(ShinyManager *self) {
#ifdef SHINY_HAS_ENABLED
if (!self->enabled) return;
#endif
_ShinyManager_appendTicksToCurNode(self);
self->_curNode = self->_curNode->parent;
}
/**/
SHINY_API void ShinyManager_preLoad(ShinyManager *self);
SHINY_API void ShinyManager_updateClean(ShinyManager *self);
SHINY_API void ShinyManager_update(ShinyManager *self);
SHINY_API void ShinyManager_clear(ShinyManager *self);
SHINY_API void ShinyManager_destroy(ShinyManager *self);
SHINY_INLINE void ShinyManager_sortZones(ShinyManager *self) {
if (self->rootZone.next)
self->_lastZone = ShinyZone_sortChain(&self->rootZone.next);
}
SHINY_API const char* ShinyManager_getOutputErrorString(ShinyManager *self);
SHINY_API int ShinyManager_output(ShinyManager *self, const char *a_filename);
SHINY_API void ShinyManager_outputToStream(ShinyManager *self, FILE *stream);
#if __cplusplus
} /* end of extern "C" */
SHINY_INLINE std::string ShinyManager_outputTreeToString(ShinyManager *self) {
const char* error = ShinyManager_getOutputErrorString(self);
if (error) return error;
else return ShinyNodesToString(&self->rootNode, self->nodeCount);
}
SHINY_INLINE std::string ShinyManager_outputFlatToString(ShinyManager *self) {
const char* error = ShinyManager_getOutputErrorString(self);
if (error) return error;
ShinyManager_sortZones(self);
return ShinyZonesToString(&self->rootZone, self->zoneCount);
}
extern "C" { /* end of c++ */
#endif
SHINY_INLINE int ShinyManager_isZoneSelfTimeBelow(ShinyManager *self, ShinyZone* a_zone, float a_percentage) {
return a_percentage * (float) self->rootZone.data.childTicks.cur
<= (float) a_zone->data.selfTicks.cur;
}
SHINY_INLINE int ShinyManager_isZoneTotalTimeBelow(ShinyManager *self, ShinyZone* a_zone, float a_percentage) {
return a_percentage * (float) self->rootZone.data.childTicks.cur
<= (float) ShinyData_totalTicksCur(&a_zone->data);
}
/**/
SHINY_INLINE void ShinyManager_enumerateNodes(ShinyManager *self, void (*a_func)(const ShinyNode*)) {
ShinyNode_enumerateNodes(&self->rootNode, a_func);
}
SHINY_INLINE void ShinyManager_enumerateZones(ShinyManager *self, void (*a_func)(const ShinyZone*)) {
ShinyZone_enumerateZones(&self->rootZone, a_func);
}
#if __cplusplus
} /* end of extern "C" */
template <class T> void ShinyManager_enumerateNodes(ShinyManager *self, T* a_this, void (T::*a_func)(const ShinyNode*)) {
ShinyNode_enumerateNodes(&self->rootNode, a_this, a_func);
}
template <class T> void ShinyManager_enumerateZones(ShinyManager *self, T* a_this, void (T::*a_func)(const ShinyZone*)) {
ShinyZone_enumerateZones(&self->rootZone, a_this, a_func);
}
extern "C" { /* end of c++ */
#endif
/*---------------------------------------------------------------------------*/
#if __cplusplus
} /* end of extern "C" */
class ShinyEndNodeOnDestruction {
public:
SHINY_INLINE ~ShinyEndNodeOnDestruction() {
ShinyManager_endCurNode(&Shiny_instance);
}
};
#endif
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_MANAGER_H */

130
xs/src/Shiny/ShinyNode.c Normal file
View File

@ -0,0 +1,130 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyNode.h"
#include "ShinyZone.h"
#include "ShinyNodeState.h"
#include <memory.h>
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
ShinyNode _ShinyNode_dummy = {
/* _last = */ { 0, 0 },
/* zone = */ NULL,
/* parent = */ NULL,
/* nextSibling = */ NULL,
/* firstChild = */ NULL,
/* lastChild = */ NULL
};
/*---------------------------------------------------------------------------*/
void ShinyNode_updateTree(ShinyNode* first, float a_damping) {
ShinyNodeState *top = NULL;
ShinyNode *node = first;
for (;;) {
do {
top = ShinyNodeState_push(top, node);
node = node->firstChild;
} while (node);
for (;;) {
node = ShinyNodeState_finishAndGetNext(top, a_damping);
top = ShinyNodeState_pop(top);
if (node) break;
else if (!top) return;
}
}
}
/*---------------------------------------------------------------------------*/
void ShinyNode_updateTreeClean(ShinyNode* first) {
ShinyNodeState *top = NULL;
ShinyNode *node = first;
for (;;) {
do {
top = ShinyNodeState_push(top, node);
node = node->firstChild;
} while (node);
for (;;) {
node = ShinyNodeState_finishAndGetNextClean(top);
top = ShinyNodeState_pop(top);
if (node) break;
else if (!top) return;
}
}
}
/*---------------------------------------------------------------------------*/
const ShinyNode* ShinyNode_findNextInTree(const ShinyNode* self) {
if (self->firstChild) {
return self->firstChild;
} else if (self->nextSibling) {
return self->nextSibling;
} else {
ShinyNode* pParent = self->parent;
while (!ShinyNode_isRoot(pParent)) {
if (pParent->nextSibling) return pParent->nextSibling;
else pParent = pParent->parent;
}
return NULL;
}
}
/*---------------------------------------------------------------------------*/
void ShinyNode_clear(ShinyNode* self) {
memset(self, 0, sizeof(ShinyNode));
}
/*---------------------------------------------------------------------------*/
void ShinyNode_enumerateNodes(const ShinyNode* a_node, void (*a_func)(const ShinyNode*)) {
a_func(a_node);
if (a_node->firstChild) ShinyNode_enumerateNodes(a_node->firstChild, a_func);
if (a_node->nextSibling) ShinyNode_enumerateNodes(a_node->nextSibling, a_func);
}
#endif

137
xs/src/Shiny/ShinyNode.h Normal file
View File

@ -0,0 +1,137 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_NODE_H
#define SHINY_NODE_H
#include "ShinyData.h"
#include "ShinyTools.h"
#ifdef SHINY_IS_COMPILED
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct _ShinyNode {
ShinyLastData _last;
struct _ShinyZone* zone;
struct _ShinyNode* parent;
struct _ShinyNode* nextSibling;
struct _ShinyNode* firstChild;
struct _ShinyNode* lastChild;
uint32_t childCount;
uint32_t entryLevel;
ShinyNodeCache* _cache;
ShinyData data;
} ShinyNode;
/*---------------------------------------------------------------------------*/
extern ShinyNode _ShinyNode_dummy;
/*---------------------------------------------------------------------------*/
SHINY_INLINE void ShinyNode_addChild(ShinyNode* self, ShinyNode* a_child) {
if (self->childCount++) {
self->lastChild->nextSibling = a_child;
self->lastChild = a_child;
} else {
self->lastChild = a_child;
self->firstChild = a_child;
}
}
SHINY_INLINE void ShinyNode_init(ShinyNode* self, ShinyNode* a_parent, struct _ShinyZone* a_zone, ShinyNodeCache* a_cache) {
/* NOTE: all member variables are assumed to be zero when allocated */
self->zone = a_zone;
self->parent = a_parent;
self->entryLevel = a_parent->entryLevel + 1;
ShinyNode_addChild(a_parent, self);
self->_cache = a_cache;
}
SHINY_API void ShinyNode_updateTree(ShinyNode* self, float a_damping);
SHINY_API void ShinyNode_updateTreeClean(ShinyNode* self);
SHINY_INLINE void ShinyNode_destroy(ShinyNode* self) {
*(self->_cache) = &_ShinyNode_dummy;
}
SHINY_INLINE void ShinyNode_appendTicks(ShinyNode* self, shinytick_t a_elapsedTicks) {
self->_last.selfTicks += a_elapsedTicks;
}
SHINY_INLINE void ShinyNode_beginEntry(ShinyNode* self) {
self->_last.entryCount++;
}
SHINY_INLINE int ShinyNode_isRoot(ShinyNode* self) {
return (self->entryLevel == 0);
}
SHINY_INLINE int ShinyNode_isDummy(ShinyNode* self) {
return (self == &_ShinyNode_dummy);
}
SHINY_INLINE int ShinyNode_isEqual(ShinyNode* self, const ShinyNode* a_parent, const struct _ShinyZone* a_zone) {
return (self->parent == a_parent && self->zone == a_zone);
}
SHINY_API const ShinyNode* ShinyNode_findNextInTree(const ShinyNode* self);
SHINY_API void ShinyNode_clear(ShinyNode* self);
SHINY_API void ShinyNode_enumerateNodes(const ShinyNode* a_node, void (*a_func)(const ShinyNode*));
#if __cplusplus
} /* end of extern "C" */
template <class T>
void ShinyNode_enumerateNodes(const ShinyNode* a_node, T* a_this, void (T::*a_func)(const ShinyNode*)) {
(a_this->*a_func)(a_node);
if (a_node->firstChild) ShinyNode_enumerateNodes(a_node->firstChild, a_this, a_func);
if (a_node->nextSibling) ShinyNode_enumerateNodes(a_node->nextSibling, a_this, a_func);
}
#endif /* __cplusplus */
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_NODE_H */

View File

@ -0,0 +1,78 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyNodePool.h"
#include "ShinyTools.h"
#include <memory.h>
#include <malloc.h>
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
ShinyNodePool* ShinyNodePool_create(uint32_t a_items) {
ShinyNodePool* pPool = (ShinyNodePool*)
malloc(sizeof(ShinyNodePool) + sizeof(ShinyNode) * (a_items - 1));
pPool->nextPool = NULL;
pPool->_nextItem = &pPool->_items[0];
pPool->endOfItems = &pPool->_items[a_items];
memset(&pPool->_items[0], 0, a_items * sizeof(ShinyNode));
return pPool;
}
/*---------------------------------------------------------------------------*/
uint32_t ShinyNodePool_memoryUsageChain(ShinyNodePool *first) {
uint32_t bytes = (uint32_t) ((char*) first->endOfItems - (char*) first);
ShinyNodePool *pool = first->nextPool;
while (pool) {
bytes += (uint32_t) ((char*) pool->endOfItems - (char*) pool);
pool = pool->nextPool;
}
return bytes;
}
/*---------------------------------------------------------------------------*/
void ShinyNodePool_destroy(ShinyNodePool *self) {
ShinyNode* firstNode = ShinyNodePool_firstItem(self);
ShinyNode* lastNode = self->_nextItem;
while (firstNode != lastNode)
ShinyNode_destroy(firstNode++);
/* TODO: make this into a loop or a tail recursion */
if (self->nextPool) ShinyNodePool_destroy(self->nextPool);
free(self);
}
#endif

View File

@ -0,0 +1,72 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_NODE_POOL_H
#define SHINY_NODE_POOL_H
#include "ShinyNode.h"
#ifdef SHINY_IS_COMPILED
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct _ShinyNodePool {
struct _ShinyNodePool* nextPool;
ShinyNode *_nextItem;
ShinyNode *endOfItems;
ShinyNode _items[1];
} ShinyNodePool;
/*---------------------------------------------------------------------------*/
SHINY_INLINE ShinyNode* ShinyNodePool_firstItem(ShinyNodePool *self) {
return &(self->_items[0]);
}
SHINY_INLINE ShinyNode* ShinyNodePool_newItem(ShinyNodePool *self) {
return self->_nextItem++;
}
ShinyNodePool* ShinyNodePool_create(uint32_t a_items);
void ShinyNodePool_destroy(ShinyNodePool *self);
uint32_t ShinyNodePool_memoryUsageChain(ShinyNodePool *first);
#if __cplusplus
} /* end of extern "C" */
#endif
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_NODE_POOL_H */

View File

@ -0,0 +1,109 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyNodeState.h"
#include "ShinyNode.h"
#include "ShinyZone.h"
#include <malloc.h>
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
ShinyNodeState* ShinyNodeState_push(ShinyNodeState *a_top, ShinyNode *a_node) {
ShinyZone *zone = a_node->zone;
ShinyNodeState *self = (ShinyNodeState*) malloc(sizeof(ShinyNodeState));
self->node = a_node;
self->_prev = a_top;
a_node->data.selfTicks.cur = a_node->_last.selfTicks;
a_node->data.entryCount.cur = a_node->_last.entryCount;
zone->data.selfTicks.cur += a_node->_last.selfTicks;
zone->data.entryCount.cur += a_node->_last.entryCount;
a_node->data.childTicks.cur = 0;
a_node->_last.selfTicks = 0;
a_node->_last.entryCount = 0;
self->zoneUpdating = zone->_state != SHINY_ZONE_STATE_UPDATING;
if (self->zoneUpdating) {
zone->_state = SHINY_ZONE_STATE_UPDATING;
} else {
zone->data.childTicks.cur -= a_node->data.selfTicks.cur;
}
return self;
}
/*---------------------------------------------------------------------------*/
ShinyNodeState* ShinyNodeState_pop(ShinyNodeState *a_top) {
ShinyNodeState *prev = a_top->_prev;
free(a_top);
return prev;
}
/*---------------------------------------------------------------------------*/
ShinyNode* ShinyNodeState_finishAndGetNext(ShinyNodeState *self, float a_damping) {
ShinyNode *node = self->node;
ShinyZone *zone = node->zone;
if (self->zoneUpdating) {
zone->data.childTicks.cur += node->data.childTicks.cur;
zone->_state = SHINY_ZONE_STATE_INITIALIZED;
}
ShinyData_computeAverage(&node->data, a_damping);
if (!ShinyNode_isRoot(node))
node->parent->data.childTicks.cur += node->data.selfTicks.cur + node->data.childTicks.cur;
return node->nextSibling;
}
/*---------------------------------------------------------------------------*/
ShinyNode* ShinyNodeState_finishAndGetNextClean(ShinyNodeState *self) {
ShinyNode *node = self->node;
ShinyZone *zone = node->zone;
if (self->zoneUpdating) {
zone->data.childTicks.cur += node->data.childTicks.cur;
zone->_state = SHINY_ZONE_STATE_INITIALIZED;
}
ShinyData_copyAverage(&node->data);
if (!ShinyNode_isRoot(node))
node->parent->data.childTicks.cur += node->data.selfTicks.cur + node->data.childTicks.cur;
return node->nextSibling;
}
#endif

View File

@ -0,0 +1,60 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_NODE_STATE_H
#define SHINY_NODE_STATE_H
#include "ShinyNode.h"
#if SHINY_IS_COMPILED == TRUE
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct _ShinyNodeState {
ShinyNode *node;
int zoneUpdating;
struct _ShinyNodeState *_prev;
} ShinyNodeState;
/*---------------------------------------------------------------------------*/
ShinyNodeState* ShinyNodeState_push(ShinyNodeState *a_top, ShinyNode *a_node);
ShinyNodeState* ShinyNodeState_pop(ShinyNodeState *a_top);
ShinyNode* ShinyNodeState_finishAndGetNext(ShinyNodeState *self, float a_damping);
ShinyNode* ShinyNodeState_finishAndGetNextClean(ShinyNodeState *self);
#if __cplusplus
} /* end of extern "C" */
#endif
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_NODE_STATE_H */

190
xs/src/Shiny/ShinyOutput.c Normal file
View File

@ -0,0 +1,190 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyOutput.h"
#include <stdio.h>
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# pragma warning(disable: 4996)
# define snprintf _snprintf
# define TRAILING 0
#else
# define TRAILING 1
#endif
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
#define OUTPUT_WIDTH_CALL 6
#define OUTPUT_WIDTH_TIME 6
#define OUTPUT_WIDTH_PERC 4
#define OUTPUT_WIDTH_SUM 79
#define OUTPUT_WIDTH_DATA (1+OUTPUT_WIDTH_CALL + 1 + 2*(OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1) + 1)
#define OUTPUT_WIDTH_NAME (OUTPUT_WIDTH_SUM - OUTPUT_WIDTH_DATA)
/*---------------------------------------------------------------------------*/
SHINY_INLINE char* printHeader(char *output, const char *a_title) {
snprintf(output, OUTPUT_WIDTH_SUM + TRAILING,
"%-*s %*s %*s %*s",
OUTPUT_WIDTH_NAME, a_title,
OUTPUT_WIDTH_CALL, "calls",
OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "self time",
OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "total time");
return output + OUTPUT_WIDTH_SUM;
}
/*---------------------------------------------------------------------------*/
SHINY_INLINE char* printData(char *output, const ShinyData *a_data, float a_topercent) {
float totalTicksAvg = ShinyData_totalTicksAvg(a_data);
const ShinyTimeUnit *selfUnit = ShinyGetTimeUnit(a_data->selfTicks.avg);
const ShinyTimeUnit *totalUnit = ShinyGetTimeUnit(totalTicksAvg);
snprintf(output, OUTPUT_WIDTH_DATA + TRAILING,
" %*.1f %*.0f %-2s %*.0f%% %*.0f %-2s %*.0f%%",
OUTPUT_WIDTH_CALL, a_data->entryCount.avg,
OUTPUT_WIDTH_TIME, a_data->selfTicks.avg * selfUnit->invTickFreq, selfUnit->suffix,
OUTPUT_WIDTH_PERC, a_data->selfTicks.avg * a_topercent,
OUTPUT_WIDTH_TIME, totalTicksAvg * totalUnit->invTickFreq, totalUnit->suffix,
OUTPUT_WIDTH_PERC, totalTicksAvg * a_topercent);
return output + OUTPUT_WIDTH_DATA;
}
/*---------------------------------------------------------------------------*/
SHINY_INLINE char* printNode(char* output, const ShinyNode *a_node, float a_topercent) {
int offset = a_node->entryLevel * 2;
snprintf(output, OUTPUT_WIDTH_NAME + TRAILING, "%*s%-*s",
offset, "", OUTPUT_WIDTH_NAME - offset, a_node->zone->name);
output += OUTPUT_WIDTH_NAME;
output = printData(output, &a_node->data, a_topercent);
return output;
}
/*---------------------------------------------------------------------------*/
SHINY_INLINE char* printZone(char* output, const ShinyZone *a_zone, float a_topercent) {
snprintf(output, OUTPUT_WIDTH_NAME + TRAILING, "%-*s",
OUTPUT_WIDTH_NAME, a_zone->name);
output += OUTPUT_WIDTH_NAME;
output = printData(output, &a_zone->data, a_topercent);
return output;
}
/*---------------------------------------------------------------------------*/
int ShinyPrintNodesSize(uint32_t a_count) {
return (1 + a_count) * (OUTPUT_WIDTH_SUM + 1);
}
/*---------------------------------------------------------------------------*/
int ShinyPrintZonesSize(uint32_t a_count) {
return (1 + a_count) * (OUTPUT_WIDTH_SUM + 1);
}
/*---------------------------------------------------------------------------*/
void ShinyPrintANode(char* output, const ShinyNode *a_node, const ShinyNode *a_root) {
float fTicksToPc = 100.0f / a_root->data.childTicks.avg;
output = printNode(output, a_node, fTicksToPc);
(*output++) = '\0';
}
/*---------------------------------------------------------------------------*/
void ShinyPrintAZone(char* output, const ShinyZone *a_zone, const ShinyZone *a_root) {
float fTicksToPc = 100.0f / a_root->data.childTicks.avg;
output = printZone(output, a_zone, fTicksToPc);
(*output++) = '\0';
}
/*---------------------------------------------------------------------------*/
void ShinyPrintNodes(char* output, const ShinyNode *a_root) {
float fTicksToPc = 100.0f / a_root->data.childTicks.avg;
const ShinyNode *node = a_root;
output = printHeader(output, "call tree");
(*output++) = '\n';
for (;;) {
output = printNode(output, node, fTicksToPc);
node = ShinyNode_findNextInTree(node);
if (node) {
(*output++) = '\n';
} else {
(*output++) = '\0';
return;
}
}
}
/*---------------------------------------------------------------------------*/
void ShinyPrintZones(char* output, const ShinyZone *a_root) {
float fTicksToPc = 100.0f / a_root->data.childTicks.avg;
const ShinyZone *zone = a_root;
output = printHeader(output, "sorted list");
(*output++) = '\n';
for (;;) {
output = printZone(output, zone, fTicksToPc);
zone = zone->next;
if (zone) {
(*output++) = '\n';
} else {
(*output++) = '\0';
return;
}
}
}
#endif

View File

@ -0,0 +1,72 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_OUTPUT_H
#define SHINY_OUTPUT_H
#include "ShinyNode.h"
#include "ShinyZone.h"
#ifdef SHINY_IS_COMPILED
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
SHINY_API int ShinyPrintNodesSize(uint32_t a_count);
SHINY_API int ShinyPrintZonesSize(uint32_t a_count);
SHINY_API void ShinyPrintANode(char* output, const ShinyNode *a_node, const ShinyNode *a_root);
SHINY_API void ShinyPrintAZone(char* output, const ShinyZone *a_zone, const ShinyZone *a_root);
SHINY_API void ShinyPrintNodes(char* output, const ShinyNode *a_root);
SHINY_API void ShinyPrintZones(char* output, const ShinyZone *a_root);
/*---------------------------------------------------------------------------*/
#if __cplusplus
} /* end of extern "C" */
#include <string>
SHINY_INLINE std::string ShinyNodesToString(const ShinyNode *a_root, uint32_t a_count) {
std::string str;
str.resize(ShinyPrintNodesSize(a_count) - 1);
ShinyPrintNodes(&str[0], a_root);
return str;
}
SHINY_INLINE std::string ShinyZonesToString(const ShinyZone *a_root, uint32_t a_count) {
std::string str;
str.resize(ShinyPrintZonesSize(a_count) - 1);
ShinyPrintZones(&str[0], a_root);
return str;
}
#endif /* __cplusplus */
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_OUTPUT_H */

149
xs/src/Shiny/ShinyPrereqs.h Normal file
View File

@ -0,0 +1,149 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_PREREQS_H
#define SHINY_PREREQS_H
#include "ShinyConfig.h"
#include "ShinyVersion.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
#define SHINY_PLATFORM_WIN32 0x1
#define SHINY_PLATFORM_POSIX 0x2
#if defined (_WIN32)
# define SHINY_PLATFORM SHINY_PLATFORM_WIN32
#else /* ASSUME: POSIX-compliant OS */
# define SHINY_PLATFORM SHINY_PLATFORM_POSIX
#endif
/*---------------------------------------------------------------------------*/
#define SHINY_COMPILER_MSVC 0x1
#define SHINY_COMPILER_GNUC 0x2
#define SHINY_COMPILER_OTHER 0x3
#if defined (_MSC_VER)
# define SHINY_COMPILER SHINY_COMPILER_MSVC
#elif defined (__GNUG__)
# define SHINY_COMPILER SHINY_COMPILER_GNUC
#else
# define SHINY_COMPILER SHINY_COMPILER_OTHER
#endif
/*---------------------------------------------------------------------------*/
#ifndef FALSE
#define FALSE 0x0
#endif
#ifndef TRUE
#define TRUE 0x1
#endif
#ifndef NULL
#define NULL 0
#endif
/*---------------------------------------------------------------------------*/
#if SHINY_COMPILER == SHINY_COMPILER_GNUC
#include <sys/types.h>
#include <stdint.h>
#endif
/*---------------------------------------------------------------------------*/
#ifdef SHINY_IS_COMPILED
struct _ShinyNode;
struct _ShinyZone;
typedef struct _ShinyNode* ShinyNodeCache;
typedef struct _ShinyNode* ShinyNodeTable;
#endif
/*---------------------------------------------------------------------------*/
#ifdef SHINY_STATIC_LINK
# define SHINY_API
#else
# define SHINY_API SHINY_EXPORT
#endif
/*---------------------------------------------------------------------------*/
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
# define SHINY_INLINE __inline
# define SHINY_UNUSED
# define SHINY_EXPORT __declspec(dllexport)
#elif SHINY_COMPILER == SHINY_COMPILER_GNUC
# define SHINY_INLINE inline
# define SHINY_UNUSED __attribute__((unused))
# define SHINY_EXPORT __attribute__((dllexport))
#elif SHINY_COMPILER == SHINY_COMPILER_OTHER
# define SHINY_INLINE inline
# define SHINY_UNUSED
# define SHINY_EXPORT extern
#endif
/*---------------------------------------------------------------------------*/
#if SHINY_COMPILER == SHINY_COMPILER_MSVC
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
/*
#elif defined(__CYGWIN__)
typedef u_int32_t uint32_t;
typedef u_int64_t uint64_t;
*/
#endif
typedef uint64_t shinytick_t;
#if __cplusplus
} /* end of extern "C" */
#endif
#endif /* SHINY_PREREQS_H */

109
xs/src/Shiny/ShinyTools.c Normal file
View File

@ -0,0 +1,109 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyTools.h"
#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
#endif /* NOMINMAX */
#include <windows.h>
#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX
#include <sys/time.h>
#endif
/*---------------------------------------------------------------------------*/
const ShinyTimeUnit* ShinyGetTimeUnit(float ticks) {
static ShinyTimeUnit units[4] = { 0 };
if (units[0].tickFreq == 0) { /* auto initialize first time */
units[0].tickFreq = ShinyGetTickFreq() / 1.0f;
units[0].invTickFreq = ShinyGetTickInvFreq() * 1.0f;
units[0].suffix = "s";
units[1].tickFreq = ShinyGetTickFreq() / 1000.0f;
units[1].invTickFreq = ShinyGetTickInvFreq() * 1000.0f;
units[1].suffix = "ms";
units[2].tickFreq = ShinyGetTickFreq() / 1000000.0f;
units[2].invTickFreq = ShinyGetTickInvFreq() * 1000000.0f;
units[2].suffix = "us";
units[3].tickFreq = ShinyGetTickFreq() / 1000000000.0f;
units[3].invTickFreq = ShinyGetTickInvFreq() * 1000000000.0f;
units[3].suffix = "ns";
}
if (units[0].tickFreq < ticks) return &units[0];
else if (units[1].tickFreq < ticks) return &units[1];
else if (units[2].tickFreq < ticks) return &units[2];
else return &units[3];
}
/*---------------------------------------------------------------------------*/
#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32
void ShinyGetTicks(shinytick_t *p) {
QueryPerformanceCounter((LARGE_INTEGER*)(p));
}
shinytick_t ShinyGetTickFreq(void) {
static shinytick_t freq = 0;
if (freq == 0) QueryPerformanceFrequency((LARGE_INTEGER*)(&freq));
return freq;
}
float ShinyGetTickInvFreq(void) {
static float invfreq = 0;
if (invfreq == 0) invfreq = 1.0f / ShinyGetTickFreq();
return invfreq;
}
/*---------------------------------------------------------------------------*/
#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX
void ShinyGetTicks(shinytick_t *p) {
timeval time;
gettimeofday(&time, NULL);
*p = time.tv_sec * 1000000 + time.tv_usec;
}
const shinytick_t& ShinyGetTickFreq(void) {
return 1000000;
}
float ShinyGetTickInvFreq(void) {
return 1.0f / 1000000.0f;
}
#endif

57
xs/src/Shiny/ShinyTools.h Normal file
View File

@ -0,0 +1,57 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_TOOLS_H
#define SHINY_TOOLS_H
#include "ShinyPrereqs.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
typedef struct {
float tickFreq;
float invTickFreq;
const char* suffix;
} ShinyTimeUnit;
/*---------------------------------------------------------------------------*/
SHINY_API const ShinyTimeUnit* ShinyGetTimeUnit(float ticks);
SHINY_API void ShinyGetTicks(shinytick_t *p);
SHINY_API shinytick_t ShinyGetTickFreq(void);
SHINY_API float ShinyGetTickInvFreq(void);
#if __cplusplus
} /* end of extern "C" */
#endif
#endif /* SHINY_TOOLS_H */

View File

@ -0,0 +1,37 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_VERSION_H
#define SHINY_VERSION_H
/*---------------------------------------------------------------------------*/
#define SHINY_VERSION "2.6 RC1"
#define SHINY_SHORTNAME "Shiny"
#define SHINY_FULLNAME "Shiny Profiler"
#define SHINY_COPYRIGHT "Copyright (C) 2007-2010 Aidin Abedi"
#define SHINY_DESCRIPTION "Shiny is a state of the art profiler designed to help finding bottlenecks in your project."
#endif /* SHINY_VERSION_H */

201
xs/src/Shiny/ShinyZone.c Normal file
View File

@ -0,0 +1,201 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ShinyZone.h"
#include <memory.h>
#if SHINY_IS_COMPILED == TRUE
/*---------------------------------------------------------------------------*/
void ShinyZone_preUpdateChain(ShinyZone *first) {
ShinyZone* zone = first;
while (zone) {
ShinyData_clearCurrent(&(zone->data));
zone = zone->next;
}
}
/*---------------------------------------------------------------------------*/
void ShinyZone_updateChain(ShinyZone *first, float a_damping) {
ShinyZone* zone = first;
do {
ShinyData_computeAverage(&(zone->data), a_damping);
zone = zone->next;
} while (zone);
}
/*---------------------------------------------------------------------------*/
void ShinyZone_updateChainClean(ShinyZone *first) {
ShinyZone* zone = first;
do {
ShinyData_copyAverage(&(zone->data));
zone = zone->next;
} while (zone);
}
/*---------------------------------------------------------------------------*/
void ShinyZone_resetChain(ShinyZone *first) {
ShinyZone* zone = first, *temp;
do {
zone->_state = SHINY_ZONE_STATE_HIDDEN;
temp = zone->next;
zone->next = NULL;
zone = temp;
} while (zone);
}
/*---------------------------------------------------------------------------*/
/* A Linked-List Memory Sort
by Philip J. Erdelsky
pje@efgh.com
http://www.alumni.caltech.edu/~pje/
Modified by Aidin Abedi
*/
ShinyZone* ShinyZone_sortChain(ShinyZone **first) /* return ptr to last zone */
{
ShinyZone *p = *first;
unsigned base;
unsigned long block_size;
struct tape
{
ShinyZone *first, *last;
unsigned long count;
} tape[4];
/* Distribute the records alternately to tape[0] and tape[1]. */
tape[0].count = tape[1].count = 0L;
tape[0].first = NULL;
base = 0;
while (p != NULL)
{
ShinyZone *next = p->next;
p->next = tape[base].first;
tape[base].first = p;
tape[base].count++;
p = next;
base ^= 1;
}
/* If the list is empty or contains only a single record, then */
/* tape[1].count == 0L and this part is vacuous. */
for (base = 0, block_size = 1L; tape[base+1].count != 0L;
base ^= 2, block_size <<= 1)
{
int dest;
struct tape *tape0, *tape1;
tape0 = tape + base;
tape1 = tape + base + 1;
dest = base ^ 2;
tape[dest].count = tape[dest+1].count = 0;
for (; tape0->count != 0; dest ^= 1)
{
unsigned long n0, n1;
struct tape *output_tape = tape + dest;
n0 = n1 = block_size;
while (1)
{
ShinyZone *chosen_record;
struct tape *chosen_tape;
if (n0 == 0 || tape0->count == 0)
{
if (n1 == 0 || tape1->count == 0)
break;
chosen_tape = tape1;
n1--;
}
else if (n1 == 0 || tape1->count == 0)
{
chosen_tape = tape0;
n0--;
}
else if (ShinyZone_compare(tape1->first, tape0->first) > 0)
{
chosen_tape = tape1;
n1--;
}
else
{
chosen_tape = tape0;
n0--;
}
chosen_tape->count--;
chosen_record = chosen_tape->first;
chosen_tape->first = chosen_record->next;
if (output_tape->count == 0)
output_tape->first = chosen_record;
else
output_tape->last->next = chosen_record;
output_tape->last = chosen_record;
output_tape->count++;
}
}
}
if (tape[base].count > 1L) {
ShinyZone* last = tape[base].last;
*first = tape[base].first;
last->next = NULL;
return last;
} else {
return NULL;
}
}
/*---------------------------------------------------------------------------*/
void ShinyZone_clear(ShinyZone* self) {
memset(self, 0, sizeof(ShinyZone));
}
/*---------------------------------------------------------------------------*/
void ShinyZone_enumerateZones(const ShinyZone* a_zone, void (*a_func)(const ShinyZone*)) {
a_func(a_zone);
if (a_zone->next) ShinyZone_enumerateZones(a_zone->next, a_func);
}
#endif

95
xs/src/Shiny/ShinyZone.h Normal file
View File

@ -0,0 +1,95 @@
/*
The MIT License
Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef SHINY_ZONE_H
#define SHINY_ZONE_H
#include "ShinyData.h"
#include <memory.h>
#ifdef SHINY_IS_COMPILED
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
#define SHINY_ZONE_STATE_HIDDEN 0
#define SHINY_ZONE_STATE_INITIALIZED 1
#define SHINY_ZONE_STATE_UPDATING 2
/*---------------------------------------------------------------------------*/
typedef struct _ShinyZone {
struct _ShinyZone* next;
int _state;
const char* name;
ShinyData data;
} ShinyZone;
/*---------------------------------------------------------------------------*/
SHINY_INLINE void ShinyZone_init(ShinyZone *self, ShinyZone* a_prev) {
self->_state = SHINY_ZONE_STATE_INITIALIZED;
a_prev->next = self;
}
SHINY_INLINE void ShinyZone_uninit(ShinyZone *self) {
self->_state = SHINY_ZONE_STATE_HIDDEN;
self->next = NULL;
}
SHINY_API void ShinyZone_preUpdateChain(ShinyZone *first);
SHINY_API void ShinyZone_updateChain(ShinyZone *first, float a_damping);
SHINY_API void ShinyZone_updateChainClean(ShinyZone *first);
SHINY_API void ShinyZone_resetChain(ShinyZone *first);
SHINY_API ShinyZone* ShinyZone_sortChain(ShinyZone **first);
SHINY_INLINE float ShinyZone_compare(ShinyZone *a, ShinyZone *b) {
return a->data.selfTicks.avg - b->data.selfTicks.avg;
}
SHINY_API void ShinyZone_clear(ShinyZone* self);
SHINY_API void ShinyZone_enumerateZones(const ShinyZone* a_zone, void (*a_func)(const ShinyZone*));
#if __cplusplus
} /* end of extern "C" */
template <class T>
void ShinyZone_enumerateZones(const ShinyZone* a_zone, T* a_this, void (T::*a_func)(const ShinyZone*)) {
(a_this->*a_func)(a_zone);
if (a_zone->next) ShinyZone_enumerateZones(a_zone->next, a_this, a_func);
}
#endif /* __cplusplus */
#endif /* if SHINY_IS_COMPILED == TRUE */
#endif /* SHINY_ZONE_H */