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)
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++];