Eric Pouech wrote:
Markus Amsler a écrit :
Eric Pouech wrote:
Markus Amsler a écrit :
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).
Hi Markus,
does the slightly modified version of pool_heap improve your performances (it shouldn't modify the perf for large files(or just a bit), but should reduce memory consumption for small pools (from 1 to 2M depending on your configuration)

A+
No, performance is exactly the same as pool_heap :( .
I analyzed why your original insert_first version was slower and memory hungrier then pool_heap. It turned out pool_realloc is the problem, not pool_alloc. First there's a memory leak, if the memory is moved the old one is not freed. Second pool_realloc is O(n) that's the reason for the speed hits. Directly using heap functions for reallocs solves both problems (but looks to hackish to get commited, perhaps you have a better idea).

Here the results for pool_realloc on top of insert_first
pool_realloc            4.5s        54M
pool_realloc,r300 17s 104M The next problem is vector_iter_[up|down], because vector_position is O(n). Explicitly storing the current iter position speeds r300 up to 8s (from original 115s)! But I'm not sure how to implement it cleanly. Directly use for() instead of vector_iter_*(), use an iterator, ...

Markus
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;
 }
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index a84d91c..61b4e48 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -39,6 +39,8 @@ struct pool /* poor's man */
 {
     struct pool_arena*  first;
     unsigned            arena_size;
+    void**              reallocs;
+    unsigned            realloc_size;
 };
 
 void     pool_init(struct pool* a, unsigned arena_size);
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index c3ccaf5..a9f6f44 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -42,12 +42,15 @@ void pool_init(struct pool* a, unsigned arena_size)
 {
     a->arena_size = arena_size;
     a->first = NULL;
+    a->reallocs = NULL;
+    a->realloc_size = 0;
 }
 
 void pool_destroy(struct pool* pool)
 {
     struct pool_arena*  arena;
     struct pool_arena*  next;
+    unsigned            i;
 
 #ifdef USE_STATS
     unsigned    alloc, used, num;
@@ -68,6 +71,11 @@ void pool_destroy(struct pool* pool)
         next = arena->next;
         HeapFree(GetProcessHeap(), 0, arena);
     }
+    for (i=0; i<pool->realloc_size; i++)
+    {
+        HeapFree(GetProcessHeap(), 0, pool->reallocs[i]);
+    }
+    if (pool->reallocs) HeapFree(GetProcessHeap(), 0, pool->reallocs);
     pool_init(pool, 0);
 }
 
@@ -99,31 +107,39 @@ void* pool_alloc(struct pool* pool, unsigned len)
     return ret;
 }
 
-static struct pool_arena* pool_is_last(const struct pool* pool, const void* p, unsigned old_size)
+static void* pool_realloc(struct pool* pool, void* p, unsigned new_size)
 {
-    struct pool_arena*  arena;
+    void* ret;
 
-    for (arena = pool->first; arena; arena = arena->next)
+    if (p)
     {
-        if (arena->current == (const char*)p + old_size) return arena;
+        ret = HeapReAlloc(GetProcessHeap(), 0, p, new_size);
+        if (ret != p)
+        {
+            /* ReAlloc moved the memory, replace the cached pointer */
+            unsigned    i;
+            for (i=0; i<pool->realloc_size; i++)
+            {
+                if (pool->reallocs[i] == p)
+                {
+                    pool->reallocs[i] = ret;
+                    break;
+                }
+            }
+        }
+        return ret;
     }
-    return NULL;
-}
 
-static void* pool_realloc(struct pool* pool, void* p, unsigned old_size, unsigned new_size)
-{
-    struct pool_arena*  arena;
-    void*               new;
+    ret = HeapAlloc(GetProcessHeap(), 0, new_size);
+    if (!pool->reallocs)
+        pool->reallocs = HeapAlloc(GetProcessHeap(), 0, sizeof(void*));
+    else
+        pool->reallocs = HeapReAlloc(GetProcessHeap(), 0, pool->reallocs, (pool->realloc_size+1)*sizeof(void*));
 
-    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;
+    pool->reallocs[pool->realloc_size] = ret;
+    pool->realloc_size++;
+
+    return ret;
 }
 
 char* pool_strdup(struct pool* pool, const char* str)
@@ -179,7 +195,6 @@ void* vector_add(struct vector* v, struct pool* pool)
     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*));
         v->buckets[v->num_buckets] = pool_alloc(pool, v->elt_size << v->shift);
         return v->buckets[v->num_buckets++];


Reply via email to