I've played around with dbghelp performance. My test case was breaking
at an unknown symbol (break gaga) while WoW was loaded in the debugger
(wine winedbg WoW.exe). The time was hand stopped, memory usage measured
with ps -AF and looked at the RSS column.
Test Time(s) Memory Usage(MB)
current git 4.5 54
pool_heap.patch 4.5 63
process_heap.patch 4.5 126
insert_first.patch 4.5 54
current git, r300 115 146
pool_heap.patch, r300 17 119
process_heap.patch, r300 17 260
insert_first.patch, r300 27 167
insert_first is the patch from Eric Pouech.
r300 means with the debug version of Mesas r300_dri.so, which has a
total compilation unit size of around 9.2M (compared to the second
biggest Wines user32 with 1.1M).
Conclusions:
- current git wins with small debug files (<2M or so), pool_heap wins
with bigger files. insert_first, process_heap are out.
- small pools have less memory overhead than small heaps
- big pools have more memory overhead than big heaps.
- big pools are a lot slower than big heaps.
IMO the best results would give removing the pools (like in
process_heap) and freeing unused memory manually, the other way round it
was allocated. But at a first glance it looks like quite a bit of work,
which I'm not sure is worth the result. I think the best approach would
be to code some destroy functions in storage.c which would free the
allocated vector, sparse_array and hash_table memory. And then gradually
replace pool_alloc calls with HeapAlloc/HeapFree pairs.
Markus
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index a84d91c..8fd3360 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -37,8 +37,7 @@
struct pool /* poor's man */
{
- struct pool_arena* first;
- unsigned arena_size;
+ HANDLE heap;
};
void pool_init(struct pool* a, unsigned arena_size);
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index e196143..3b1e909 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -32,100 +32,24 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
-struct pool_arena
-{
- struct pool_arena* next;
- char* current;
-};
-
void pool_init(struct pool* a, unsigned arena_size)
{
- a->arena_size = arena_size;
- a->first = NULL;
+ a->heap = HeapCreate(0, arena_size, 0);
}
void pool_destroy(struct pool* pool)
{
- struct pool_arena* arena;
- struct pool_arena* next;
-
-#ifdef USE_STATS
- unsigned alloc, used, num;
-
- for (alloc = used = num = 0, arena = pool->first; arena; arena = arena->next)
- {
- alloc += pool->arena_size;
- used += arena->current - (char*)arena;
- num++;
- }
- FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
- "\t\t\t\tnon-allocation ratio: %.2f%%\n",
- pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
-#endif
-
- for (arena = pool->first; arena; arena = next)
- {
- next = arena->next;
- HeapFree(GetProcessHeap(), 0, arena);
- }
- pool_init(pool, 0);
+ HeapDestroy(pool->heap);
}
void* pool_alloc(struct pool* pool, unsigned len)
{
- struct pool_arena** parena;
- struct pool_arena* arena;
- void* ret;
-
- len = (len + 3) & ~3; /* round up size on DWORD boundary */
- assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
-
- for (parena = &pool->first; *parena; parena = &(*parena)->next)
- {
- if ((char*)(*parena) + pool->arena_size - (*parena)->current >= len)
- {
- ret = (*parena)->current;
- (*parena)->current += len;
- return ret;
- }
- }
-
- arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
- if (!arena) {FIXME("OOM\n");return NULL;}
-
- *parena = arena;
-
- ret = (char*)arena + sizeof(*arena);
- arena->next = NULL;
- arena->current = (char*)ret + len;
- return ret;
-}
-
-static struct pool_arena* pool_is_last(const struct pool* pool, const void* p, unsigned old_size)
-{
- struct pool_arena* arena;
-
- for (arena = pool->first; arena; arena = arena->next)
- {
- if (arena->current == (const char*)p + old_size) return arena;
- }
- return NULL;
+ return HeapAlloc(pool->heap, 0, len);
}
-static void* pool_realloc(struct pool* pool, void* p, unsigned old_size, unsigned new_size)
+static void* pool_realloc(struct pool* pool, void* p, unsigned len)
{
- struct pool_arena* arena;
- void* new;
-
- if ((arena = pool_is_last(pool, p, old_size)) &&
- (char*)p + new_size <= (char*)arena + pool->arena_size)
- {
- arena->current = (char*)p + new_size;
- return p;
- }
- if ((new = pool_alloc(pool, new_size)) && old_size)
- memcpy(new, p, min(old_size, new_size));
- return new;
+ return HeapReAlloc(pool->heap, 0, p, len);
}
char* pool_strdup(struct pool* pool, const char* str)
@@ -180,9 +104,14 @@ void* vector_add(struct vector* v, struct pool* pool)
assert(v->num_elts > ncurr);
if (ncurr == (v->num_buckets << v->shift))
{
- v->buckets = pool_realloc(pool, v->buckets,
- v->num_buckets * sizeof(void*),
- (v->num_buckets + 1) * sizeof(void*));
+ if (v->buckets)
+ {
+ v->buckets = pool_realloc(pool, v->buckets, (v->num_buckets + 1) * sizeof(void*));
+ }
+ else
+ {
+ v->buckets = pool_alloc(pool, (v->num_buckets + 1) * sizeof(void*));
+ }
v->buckets[v->num_buckets] = pool_alloc(pool, v->elt_size << v->shift);
return v->buckets[v->num_buckets++];
}
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index e196143..6538272 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -32,100 +32,28 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
-struct pool_arena
-{
- struct pool_arena* next;
- char* current;
-};
-
void pool_init(struct pool* a, unsigned arena_size)
{
- a->arena_size = arena_size;
- a->first = NULL;
+ return;
}
void pool_destroy(struct pool* pool)
{
- struct pool_arena* arena;
- struct pool_arena* next;
-
-#ifdef USE_STATS
- unsigned alloc, used, num;
-
- for (alloc = used = num = 0, arena = pool->first; arena; arena = arena->next)
- {
- alloc += pool->arena_size;
- used += arena->current - (char*)arena;
- num++;
- }
- FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
- "\t\t\t\tnon-allocation ratio: %.2f%%\n",
- pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
-#endif
-
- for (arena = pool->first; arena; arena = next)
- {
- next = arena->next;
- HeapFree(GetProcessHeap(), 0, arena);
- }
- pool_init(pool, 0);
+ return;
}
void* pool_alloc(struct pool* pool, unsigned len)
{
- struct pool_arena** parena;
- struct pool_arena* arena;
- void* ret;
-
- len = (len + 3) & ~3; /* round up size on DWORD boundary */
- assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
-
- for (parena = &pool->first; *parena; parena = &(*parena)->next)
- {
- if ((char*)(*parena) + pool->arena_size - (*parena)->current >= len)
- {
- ret = (*parena)->current;
- (*parena)->current += len;
- return ret;
- }
- }
-
- arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
- if (!arena) {FIXME("OOM\n");return NULL;}
-
- *parena = arena;
-
- ret = (char*)arena + sizeof(*arena);
- arena->next = NULL;
- arena->current = (char*)ret + len;
- return ret;
-}
-
-static struct pool_arena* pool_is_last(const struct pool* pool, const void* p, unsigned old_size)
-{
- struct pool_arena* arena;
-
- for (arena = pool->first; arena; arena = arena->next)
- {
- if (arena->current == (const char*)p + old_size) return arena;
- }
- return NULL;
+ return HeapAlloc(GetProcessHeap(), 0, len);
}
static void* pool_realloc(struct pool* pool, void* p, unsigned old_size, unsigned new_size)
{
- struct pool_arena* arena;
- void* new;
-
- if ((arena = pool_is_last(pool, p, old_size)) &&
- (char*)p + new_size <= (char*)arena + pool->arena_size)
- {
- arena->current = (char*)p + new_size;
- return p;
+ if(p){
+ return HeapReAlloc(GetProcessHeap(), 0, p, new_size);
+ } else {
+ return HeapAlloc(GetProcessHeap(), 0, new_size);
}
- if ((new = pool_alloc(pool, new_size)) && old_size)
- memcpy(new, p, min(old_size, new_size));
- return new;
}
char* pool_strdup(struct pool* pool, const char* str)
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index e196143..c3ccaf5 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -73,30 +73,28 @@ void pool_destroy(struct pool* pool)
void* pool_alloc(struct pool* pool, unsigned len)
{
- struct pool_arena** parena;
struct pool_arena* arena;
void* ret;
len = (len + 3) & ~3; /* round up size on DWORD boundary */
assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
- for (parena = &pool->first; *parena; parena = &(*parena)->next)
+ for (arena = pool->first; arena; arena = arena->next)
{
- if ((char*)(*parena) + pool->arena_size - (*parena)->current >= len)
+ if ((char*)arena + pool->arena_size - arena->current >= len)
{
- ret = (*parena)->current;
- (*parena)->current += len;
+ ret = arena->current;
+ arena->current += len;
return ret;
}
}
-
+
arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
if (!arena) {FIXME("OOM\n");return NULL;}
- *parena = arena;
-
ret = (char*)arena + sizeof(*arena);
- arena->next = NULL;
+ arena->next = pool->first;
+ pool->first = arena;
arena->current = (char*)ret + len;
return ret;
}