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;
 }


Reply via email to