summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-05-17 21:47:10 -0300
committershennetsind <ind@henn.et>2013-05-17 21:47:10 -0300
commit104bb6c05dc8effef9db715f0b708d4548e10010 (patch)
treeda8cfebada8a4345cee998713679db54eafffd84 /src/common
parent4ef9258f0f618857ed5d9e2f9e07f33dc6d13559 (diff)
downloadhercules-104bb6c05dc8effef9db715f0b708d4548e10010.tar.gz
hercules-104bb6c05dc8effef9db715f0b708d4548e10010.tar.bz2
hercules-104bb6c05dc8effef9db715f0b708d4548e10010.tar.xz
hercules-104bb6c05dc8effef9db715f0b708d4548e10010.zip
ERS Report Redesign
greatly enhances the ability to detect memory throughput More on it: http://hercules.ws/board/blog/1/entry-30-ers-report-update/ Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/common')
-rw-r--r--src/common/db.c7
-rw-r--r--src/common/db.h10
-rw-r--r--src/common/ers.c117
-rw-r--r--src/common/ers.h6
4 files changed, 108 insertions, 32 deletions
diff --git a/src/common/db.c b/src/common/db.c
index 7ac9b2dc7..f2e69abbb 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -2400,10 +2400,10 @@ DBReleaser db_custom_release(DBRelease which)
* @see #DBMap_impl
* @see #db_fix_options(DBType,DBOptions)
*/
-DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen)
-{
+DBMap* db_alloc(const char *file, const char *func, int line, DBType type, DBOptions options, unsigned short maxlen) {
DBMap_impl* db;
unsigned int i;
+ char ers_name[50];
#ifdef DB_ENABLE_STATS
DB_COUNTSTAT(db_alloc);
@@ -2445,7 +2445,8 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
db->free_max = 0;
db->free_lock = 0;
/* Other */
- db->nodes = ers_new(sizeof(struct dbn),"db.c::db_alloc",ERS_OPT_NONE);
+ snprintf(ers_name, 50, "db_alloc:nodes:%s:%s:%d",func,file,line);
+ db->nodes = ers_new(sizeof(struct dbn),ers_name,ERS_OPT_WAIT|ERS_OPT_FREE_NAME);
db->cmp = db_default_cmp(type);
db->hash = db_default_hash(type);
db->release = db_default_release(type, options);
diff --git a/src/common/db.h b/src/common/db.h
index 4fe6a93d6..45babed78 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -653,10 +653,10 @@ struct DBMap {
#define strdb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_str2key(k),(f))) )
// Database creation and destruction macros
-#define idb_alloc(opt) db_alloc(__FILE__,__LINE__,DB_INT,(opt),sizeof(int))
-#define uidb_alloc(opt) db_alloc(__FILE__,__LINE__,DB_UINT,(opt),sizeof(unsigned int))
-#define strdb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_STRING,(opt),(maxlen))
-#define stridb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_ISTRING,(opt),(maxlen))
+#define idb_alloc(opt) db_alloc(__FILE__,__func__,__LINE__,DB_INT,(opt),sizeof(int))
+#define uidb_alloc(opt) db_alloc(__FILE__,__func__,__LINE__,DB_UINT,(opt),sizeof(unsigned int))
+#define strdb_alloc(opt,maxlen) db_alloc(__FILE__,__func__,__LINE__,DB_STRING,(opt),(maxlen))
+#define stridb_alloc(opt,maxlen) db_alloc(__FILE__,__func__,__LINE__,DB_ISTRING,(opt),(maxlen))
#define db_destroy(db) ( (db)->destroy((db),NULL) )
// Other macros
#define db_clear(db) ( (db)->clear(db,NULL) )
@@ -775,7 +775,7 @@ DBReleaser db_custom_release(DBRelease which);
* @see #db_default_release(DBType,DBOptions)
* @see #db_fix_options(DBType,DBOptions)
*/
-DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen);
+DBMap* db_alloc(const char *file, const char *func, int line, DBType type, DBOptions options, unsigned short maxlen);
/**
* Manual cast from 'int' to the union DBKey.
diff --git a/src/common/ers.c b/src/common/ers.c
index 13e54b393..69b7609d6 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -50,11 +50,14 @@
#define ERS_BLOCK_ENTRIES 2048
+
struct ers_list
{
struct ers_list *Next;
};
+struct ers_instance_t;
+
typedef struct ers_cache
{
// Allocated object size, including ers_list size
@@ -75,21 +78,23 @@ typedef struct ers_cache
// Free objects count
unsigned int Free;
- // Used objects count
+ // Used blocks count
unsigned int Used;
-
+
+ // Objects in-use count
+ unsigned int UsedObjs;
+
// Linked list
struct ers_cache *Next, *Prev;
} ers_cache_t;
-typedef struct
-{
+struct ers_instance_t {
// Interface to ERS
struct eri VTable;
// Name, used for debbuging purpouses
char *Name;
-
+
// Misc options
enum ERSOptions Options;
@@ -98,11 +103,21 @@ typedef struct
// Count of objects in use, used for detecting memory leaks
unsigned int Count;
-} ers_instance_t;
+
+#ifdef DEBUG
+ /* for data analysis [Ind/Hercules] */
+ unsigned int Peak;
+ struct ers_instance_t *Next, *Prev;
+#endif
+
+};
// Array containing a pointer for all ers_cache structures
-static ers_cache_t *CacheList;
+static ers_cache_t *CacheList = NULL;
+#ifdef DEBUG
+ static struct ers_instance_t *InstanceList = NULL;
+#endif
static ers_cache_t *ers_find_cache(unsigned int size)
{
@@ -119,6 +134,7 @@ static ers_cache_t *ers_find_cache(unsigned int size)
cache->Blocks = NULL;
cache->Free = 0;
cache->Used = 0;
+ cache->UsedObjs = 0;
cache->Max = 0;
if (CacheList == NULL)
@@ -157,7 +173,7 @@ static void ers_free_cache(ers_cache_t *cache, bool remove)
static void *ers_obj_alloc_entry(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ struct ers_instance_t *instance = (struct ers_instance_t *)self;
void *ret;
if (instance == NULL)
@@ -192,13 +208,19 @@ static void *ers_obj_alloc_entry(ERS self)
}
instance->Count++;
+ instance->Cache->UsedObjs++;
+
+#ifdef DEBUG
+ if( instance->Count > instance->Peak )
+ instance->Peak = instance->Count;
+#endif
return ret;
}
static void ers_obj_free_entry(ERS self, void *entry)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ struct ers_instance_t *instance = (struct ers_instance_t *)self;
struct ers_list *reuse = (struct ers_list *)((unsigned char *)entry - sizeof(struct ers_list));
if (instance == NULL)
@@ -215,11 +237,12 @@ static void ers_obj_free_entry(ERS self, void *entry)
reuse->Next = instance->Cache->ReuseList;
instance->Cache->ReuseList = reuse;
instance->Count--;
+ instance->Cache->UsedObjs--;
}
static size_t ers_obj_entry_size(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ struct ers_instance_t *instance = (struct ers_instance_t *)self;
if (instance == NULL)
{
@@ -232,7 +255,7 @@ static size_t ers_obj_entry_size(ERS self)
static void ers_obj_destroy(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ struct ers_instance_t *instance = (struct ers_instance_t *)self;
if (instance == NULL)
{
@@ -247,13 +270,26 @@ static void ers_obj_destroy(ERS self)
if (--instance->Cache->ReferenceCount <= 0)
ers_free_cache(instance->Cache, true);
+#ifdef DEBUG
+ if (instance->Next)
+ instance->Next->Prev = instance->Prev;
+
+ if (instance->Prev)
+ instance->Prev->Next = instance->Next;
+ else
+ InstanceList = instance->Next;
+#endif
+
+ if( instance->Options & ERS_OPT_FREE_NAME )
+ aFree(instance->Name);
+
aFree(instance);
}
ERS ers_new(uint32 size, char *name, enum ERSOptions options)
{
- ers_instance_t *instance;
- CREATE(instance, ers_instance_t, 1);
+ struct ers_instance_t *instance;
+ CREATE(instance,struct ers_instance_t, 1);
size += sizeof(struct ers_list);
if (size % ERS_ALIGNED)
@@ -264,29 +300,66 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options)
instance->VTable.entry_size = ers_obj_entry_size;
instance->VTable.destroy = ers_obj_destroy;
- instance->Name = name;
+ instance->Name = ( options & ERS_OPT_FREE_NAME ) ? aStrdup(name) : name;
instance->Options = options;
instance->Cache = ers_find_cache(size);
instance->Cache->ReferenceCount++;
+#ifdef DEBUG
+ if (InstanceList == NULL) {
+ InstanceList = instance;
+ } else {
+ instance->Next = InstanceList;
+ instance->Next->Prev = instance;
+ InstanceList = instance;
+ InstanceList->Prev = NULL;
+ }
+#endif
instance->Count = 0;
return &instance->VTable;
}
-void ers_report(void)
-{
+void ers_report(void) {
ers_cache_t *cache;
- int i = 0;
+ unsigned int cache_c = 0, blocks_u = 0, blocks_a = 0, memory_b = 0, memory_t = 0;
+#ifdef DEBUG
+ struct ers_instance_t *instance;
+ unsigned int instance_c = 0, instance_c_d = 0;
+
+ for (instance = InstanceList; instance; instance = instance->Next) {
+ instance_c++;
+ if( (instance->Options & ERS_OPT_WAIT) && !instance->Count )
+ continue;
+ instance_c_d++;
+ ShowMessage(CL_BOLD"[ERS Instance "CL_NORMAL""CL_WHITE"%s"CL_NORMAL""CL_BOLD" report]\n"CL_NORMAL, instance->Name);
+ ShowMessage("\tblock size : %u\n", instance->Cache->ObjectSize);
+ ShowMessage("\tblocks being used : %u\n", instance->Count);
+ ShowMessage("\tpeak blocks : %u\n", instance->Peak);
+ ShowMessage("\tmemory in use : %.2f MB\n", instance->Count == 0 ? 0. : (double)((instance->Count * instance->Cache->ObjectSize)/1024)/1024);
+ }
+#endif
+
for (cache = CacheList; cache; cache = cache->Next) {
- ShowMessage(CL_BOLD"[Entry manager #%u report]\n"CL_NORMAL, ++i);
+ cache_c++;
+ ShowMessage(CL_BOLD"[ERS Cache of size '"CL_NORMAL""CL_WHITE"%u"CL_NORMAL""CL_BOLD"' report]\n"CL_NORMAL, cache->ObjectSize);
ShowMessage("\tinstances : %u\n", cache->ReferenceCount);
- ShowMessage("\tblock array size : %u\n", cache->ObjectSize);
- ShowMessage("\tallocated blocks : %u\n", cache->Free+cache->Used);
- ShowMessage("\tentries being used : %u\n", cache->Used);
- ShowMessage("\tunused entries : %u\n", cache->Free);
+ ShowMessage("\tblocks in use : %u/%u\n", cache->UsedObjs, cache->UsedObjs+cache->Free);
+ ShowMessage("\tblocks unused : %u\n", cache->Free);
+ ShowMessage("\tmemory in use : %.2f MB\n", cache->UsedObjs == 0 ? 0. : (double)((cache->UsedObjs * cache->ObjectSize)/1024)/1024);
+ ShowMessage("\tmemory allocated : %.2f MB\n", (cache->Free+cache->UsedObjs) == 0 ? 0. : (double)(((cache->UsedObjs+cache->Free) * cache->ObjectSize)/1024)/1024);
+ blocks_u += cache->UsedObjs;
+ blocks_a += cache->UsedObjs + cache->Free;
+ memory_b += cache->UsedObjs * cache->ObjectSize;
+ memory_t += (cache->UsedObjs+cache->Free) * cache->ObjectSize;
}
+#ifdef DEBUG
+ ShowInfo("ers_report: '"CL_WHITE"%u"CL_NORMAL"' instances in use, '"CL_WHITE"%u"CL_NORMAL"' displayed\n",instance_c,instance_c_d);
+#endif
+ ShowInfo("ers_report: '"CL_WHITE"%u"CL_NORMAL"' caches in use\n",cache_c);
+ ShowInfo("ers_report: '"CL_WHITE"%u"CL_NORMAL"' blocks in use, consuming '"CL_WHITE"%.2f MB"CL_NORMAL"'\n",blocks_u,(double)((memory_b)/1024)/1024);
+ ShowInfo("ers_report: '"CL_WHITE"%u"CL_NORMAL"' blocks total, consuming '"CL_WHITE"%.2f MB"CL_NORMAL"' \n",blocks_a,(double)((memory_t)/1024)/1024);
}
void ers_force_destroy_all(void)
diff --git a/src/common/ers.h b/src/common/ers.h
index dc66af5ef..4871d8d50 100644
--- a/src/common/ers.h
+++ b/src/common/ers.h
@@ -71,8 +71,10 @@
#endif /* not ERS_ALIGN_ENTRY */
enum ERSOptions {
- ERS_OPT_NONE = 0,
- ERS_OPT_CLEAR = 1,/* silently clears any entries left in the manager upon destruction */
+ ERS_OPT_NONE = 0x0,
+ ERS_OPT_CLEAR = 0x1,/* silently clears any entries left in the manager upon destruction */
+ ERS_OPT_WAIT = 0x2,/* wait for entries to come in order to list! */
+ ERS_OPT_FREE_NAME = 0x4,/* name is dynamic memory, and should be freed */
};
/**