dbghelp performance
Eric Pouech
eric.pouech at wanadoo.fr
Sat May 5 07:46:36 CDT 2007
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).
>>>
>>> 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.
>> thanks for the testings & timings !
>>
>> you're also missing a couple of elements:
>> - for the memory overhead, in the first case you consider 50 MB
>> (roughly) over 10 or 20 modules while in your r300 case the impact
>> (and memory difference) is only on a single module
> I'm not sure what's your point is.
>> - time to unload a module hasn't been computed (it's less used than
>> loading a module)
> Unloading is more or less instant in all cases.
>> what's also strange is that the pool_heap gets lower memory
>> consumption than the process heap one, which is rather not a natural
>> result... I wonder if some data haven't been swapped out and aren't
>> accounted for in RSS
> The process_heap is the one I sent to wine-patches, which never frees
> any memory.
> I've also tested an improved process_heap, which stores the allocated
> memory pointer in an array and frees it afterwards. Without luck, it's
> slower and uses more memory the pool_heap.
>
> So I don't see a simple solution which only affects storage.c, is
> equal or better than the current, and is significantly faster at big
> debug files. Any ideas?
>
> Markus
>
>
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+
--
Eric Pouech
"The problem with designing something completely foolproof is to underestimate the ingenuity of a complete idiot." (Douglas Adams)
-------------- next part --------------
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index a7f3235..5f8d1c4 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -35,13 +35,12 @@
/* #define USE_STATS */
-struct pool /* poor's man */
+struct pool
{
- struct pool_arena* first;
- unsigned arena_size;
+ HANDLE heap;
};
-void pool_init(struct pool* a, unsigned arena_size);
+void pool_init(struct pool* a);
void pool_destroy(struct pool* a);
void* pool_alloc(struct pool* a, unsigned len);
/* void* pool_realloc(struct pool* a, void* p,
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index bf8435f..1364834 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -1960,7 +1960,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
return FALSE;
}
- pool_init(&ctx.pool, 65536);
+ pool_init(&ctx.pool);
ctx.sections = sections;
ctx.section = section_debug;
ctx.module = module;
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c
index b844e59..75d0821 100644
--- a/dlls/dbghelp/elf_module.c
+++ b/dlls/dbghelp/elf_module.c
@@ -1131,7 +1131,7 @@ BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
return FALSE;
}
- pool_init(&pool, 65536);
+ pool_init(&pool);
hash_table_init(&pool, &ht_symtab, 256);
if (!fmap)
diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c
index 3093c58..adbdce0 100644
--- a/dlls/dbghelp/module.c
+++ b/dlls/dbghelp/module.c
@@ -138,7 +138,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
get_module_type(type, virtual), mod_addr, mod_addr + size,
debugstr_w(name));
- pool_init(&module->pool, 65536);
+ pool_init(&module->pool);
module->module.SizeOfStruct = sizeof(module->module);
module->module.BaseOfImage = mod_addr;
diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c
index e196143..6ccac54 100644
--- a/dlls/dbghelp/storage.c
+++ b/dlls/dbghelp/storage.c
@@ -38,94 +38,25 @@ struct pool_arena
char* current;
};
-void pool_init(struct pool* a, unsigned arena_size)
+void pool_init(struct pool* pool)
{
- a->arena_size = arena_size;
- a->first = NULL;
+ pool->heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 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);
+ pool->heap = NULL;
}
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 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 ((new = pool_alloc(pool, new_size)) && old_size)
- memcpy(new, p, min(old_size, new_size));
- return new;
+ return p ? HeapReAlloc(pool->heap, 0, p, new_size) : HeapAlloc(pool->heap, 0, new_size);
}
char* pool_strdup(struct pool* pool, const char* str)
@@ -181,7 +112,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++];
More information about the wine-devel
mailing list