From 6caaafbb6d662da8d2561399a35c0aeee7642a46 Mon Sep 17 00:00:00 2001 From: Tomas Kukosa Date: Fri, 30 Nov 2007 09:22:01 +0000 Subject: [PATCH] Next few improvements to speed up startup about 10%. - use GTree instead of GList for preference module lists svn path=/trunk/; revision=23679 --- epan/asm_utils.c | 6 ++ epan/asm_utils.h | 1 + epan/asm_utils_win32_x86.asm | 39 ++++++++ epan/epan.c | 3 + epan/prefs-int.h | 2 +- epan/prefs.c | 167 +++++++++++++++-------------------- epan/prefs.h | 6 ++ epan/proto.c | 8 +- 8 files changed, 133 insertions(+), 99 deletions(-) diff --git a/epan/asm_utils.c b/epan/asm_utils.c index 98044c14bc..84383baf16 100644 --- a/epan/asm_utils.c +++ b/epan/asm_utils.c @@ -41,6 +41,12 @@ wrs_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data _U_) return strcmp((const char*)a, (const char*)b); } +gboolean +wrs_str_equal(gconstpointer a, gconstpointer b) +{ + return !strcmp((const char*)a, (const char*)b); +} + guchar wrs_check_charset(const guchar table[256], const char *str) { diff --git a/epan/asm_utils.h b/epan/asm_utils.h index 21a2ef55eb..29fa3fc60c 100644 --- a/epan/asm_utils.h +++ b/epan/asm_utils.h @@ -27,6 +27,7 @@ int wrs_strcmp(gconstpointer a, gconstpointer b); int wrs_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data); +gboolean wrs_str_equal(gconstpointer a, gconstpointer b); guchar wrs_check_charset(const guchar table[256], const char *str); diff --git a/epan/asm_utils_win32_x86.asm b/epan/asm_utils_win32_x86.asm index 52143a5b00..46a1996bc7 100644 --- a/epan/asm_utils_win32_x86.asm +++ b/epan/asm_utils_win32_x86.asm @@ -26,6 +26,7 @@ SECTION .text GLOBAL _wrs_strcmp GLOBAL _wrs_strcmp_with_data +GLOBAL _wrs_str_equal GLOBAL _wrs_check_charset GLOBAL _wrs_str_hash @@ -70,6 +71,44 @@ CMP_NEQ_END: inc eax retn + align 16 +_wrs_str_equal + mov ecx, dword [esp + 4] ; a + mov edx, dword [esp + 8] ; b + push ebx +EQL_LOOP: + mov eax, dword [ecx] + mov ebx, dword [edx] + cmp al, bl + jne EQL_NEQ_END + or al, al + jz EQL_EQ_END + cmp ah, bh + jne EQL_NEQ_END + or ah, ah + jz EQL_EQ_END + shr eax, 16 + shr ebx, 16 + add ecx, byte 4 + add edx, byte 4 + cmp al, bl + jne EQL_NEQ_END + or al, al + jz EQL_EQ_END + cmp ah, bh + jne EQL_NEQ_END + or ah, ah + jnz EQL_LOOP +EQL_EQ_END: + xor eax, eax + pop ebx + not eax + retn +EQL_NEQ_END: + pop ebx + xor eax, eax + retn + align 16 _wrs_check_charset: mov edx, dword [esp + 4] ; table diff --git a/epan/epan.c b/epan/epan.c index 5814f852ae..1c1c49f792 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -47,6 +47,7 @@ #include "circuit.h" #include "except.h" #include "packet.h" +#include "prefs.h" #include "column-utils.h" #include "tap.h" #include "addr_resolv.h" @@ -89,6 +90,7 @@ epan_init(void (*register_all_protocols)(register_cb cb, gpointer client_data), #endif tvbuff_init(); tap_init(); + prefs_init(); proto_init(register_all_protocols, register_all_handoffs, cb, client_data); packet_init(); dfilter_init(); @@ -108,6 +110,7 @@ epan_cleanup(void) expert_cleanup(); dfilter_cleanup(); proto_cleanup(); + prefs_cleanup(); packet_cleanup(); oid_resolv_cleanup(); tvbuff_cleanup(); diff --git a/epan/prefs-int.h b/epan/prefs-int.h index 7603049fc7..8ab014a5ff 100644 --- a/epan/prefs-int.h +++ b/epan/prefs-int.h @@ -32,7 +32,7 @@ struct pref_module { const char *description;/* Description of module (displayed in preferences notebook) */ void (*apply_cb)(void); /* routine to call when preferences applied */ GList *prefs; /* list of its preferences */ - GList *submodules; /* list of its submodules */ + GTree *submodules; /* list of its submodules */ int numprefs; /* number of non-obsolete preferences */ gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */ gboolean obsolete; /* if TRUE, this is a module that used to diff --git a/epan/prefs.c b/epan/prefs.c index 23f2c0e533..c3bfe10872 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -56,7 +56,7 @@ #endif /* Internal functions */ -static module_t *find_subtree(module_t *parent, const char *name); +static module_t *find_subtree(module_t *parent, const char *tilte); static module_t *prefs_register_module_or_subtree(module_t *parent, const char *name, const char *title, const char *description, gboolean is_subtree, void (*apply_cb)(void)); @@ -110,30 +110,33 @@ static const gchar *gui_layout_content_text[] = /* * List of all modules with preference settings. */ -static GList *modules; +static GTree *modules = NULL; /* * List of all modules that should show up at the top level of the * tree in the preference dialog box. */ -static GList *top_level_modules; +static GTree *top_level_modules = NULL; -static gint -module_compare_name(gconstpointer p1_arg, gconstpointer p2_arg) +/** Sets up memory used by proto routines. Called at program startup */ +void prefs_init(void) { - const module_t *p1 = p1_arg; - const module_t *p2 = p2_arg; + modules = g_tree_new(g_ascii_strcasecmp); + top_level_modules = g_tree_new(g_ascii_strcasecmp); - return g_ascii_strcasecmp(p1->name, p2->name); } -static gint -module_compare_title(gconstpointer p1_arg, gconstpointer p2_arg) +/** Frees memory used by proto routines. Called at program shutdown */ +void prefs_cleanup(void) { - const module_t *p1 = p1_arg; - const module_t *p2 = p2_arg; - - return g_ascii_strcasecmp(p1->title, p2->title); + if (modules) { + g_tree_destroy(modules); + modules = NULL; + } + if (top_level_modules) { + g_tree_destroy(top_level_modules); + top_level_modules = NULL; + } } /* @@ -179,9 +182,8 @@ prefs_register_module_or_subtree(module_t *parent, const char *name, module->apply_cb = apply_cb; module->description = description; - if(prefs_find_module(name) == NULL) - modules = g_list_insert_sorted(modules, module, - module_compare_name); + if (prefs_find_module(name) == NULL) + g_tree_insert(modules, (gpointer)name, module); return module; } @@ -192,7 +194,7 @@ prefs_register_module_or_subtree(module_t *parent, const char *name, module->description = description; module->apply_cb = apply_cb; module->prefs = NULL; /* no preferences, to start */ - module->submodules = NULL; /* no submodules, to start */ + module->submodules = g_tree_new(g_ascii_strcasecmp); /* no submodules, to start */ module->numprefs = 0; module->prefs_changed = FALSE; module->obsolete = FALSE; @@ -234,8 +236,7 @@ prefs_register_module_or_subtree(module_t *parent, const char *name, /* * Insert this module in the list of all modules. */ - modules = g_list_insert_sorted(modules, module, - module_compare_name); + g_tree_insert(modules, (gpointer)name, module); } else { /* * This has no name, just a title; check to make sure it's a @@ -252,14 +253,12 @@ prefs_register_module_or_subtree(module_t *parent, const char *name, /* * It goes at the top. */ - top_level_modules = g_list_insert_sorted(top_level_modules, - module, module_compare_title); + g_tree_insert(top_level_modules, (gpointer)title, module); } else { /* * It goes into the list for this module. */ - parent->submodules = g_list_insert_sorted(parent->submodules, module, - module_compare_title); + g_tree_insert(parent->submodules, (gpointer)title, module); } return module; @@ -372,18 +371,6 @@ prefs_register_protocol_obsolete(int id) return module; } -/* - * Find a module, given its name. - */ -static gint -module_match(gconstpointer a, gconstpointer b) -{ - const module_t *module = a; - const char *name = b; - - return strcmp(name, module->name); -} - #if GLIB_MAJOR_VERSION < 2 static void *discard_const(const void *const_ptr) { @@ -401,43 +388,21 @@ static void *discard_const(const void *const_ptr) module_t * prefs_find_module(const char *name) { - GList *list_entry; - -#if GLIB_MAJOR_VERSION < 2 - list_entry = g_list_find_custom(modules, discard_const(name), module_match); -#else - list_entry = g_list_find_custom(modules, name, module_match); -#endif - if (list_entry == NULL) - return NULL; /* no such module */ - return (module_t *) list_entry->data; -} - -static gint -subtree_match(gconstpointer a, gconstpointer b) -{ - const module_t *module = a; - const char *title = b; - - return strcmp(title, module->title); +#if GLIB_MAJOR_VERSION < 2 + return g_tree_lookup(modules, discard_const(name)); +#else + return g_tree_lookup(modules, name); +#endif } static module_t * find_subtree(module_t *parent, const char *name) { - GList *list_entry; - -#if GLIB_MAJOR_VERSION < 2 - list_entry = g_list_find_custom(parent ? parent->submodules : top_level_modules, - discard_const(name), subtree_match); -#else - list_entry = g_list_find_custom(parent ? parent->submodules : top_level_modules, - name, subtree_match); -#endif - - if (list_entry == NULL) - return NULL; /* no such module */ - return (module_t *) list_entry->data; +#if GLIB_MAJOR_VERSION < 2 + return g_tree_lookup(parent ? parent->submodules : top_level_modules, discard_const(name)); +#else + return g_tree_lookup(parent ? parent->submodules : top_level_modules, name); +#endif } /* @@ -452,27 +417,39 @@ find_subtree(module_t *parent, const char *name) * silently ignored in preference files. Does not ignore subtrees, * as this can be used when walking the display tree of modules. */ + +typedef struct { + module_cb callback; + gpointer user_data; + guint ret; +} call_foreach_t; + +static gboolean +call_foreach_cb(gpointer key _U_, gpointer value, gpointer data) +{ + module_t *module = (module_t*)value; + call_foreach_t *call_data = (call_foreach_t*)data; + + if (!module->obsolete) { + call_data->ret = (*call_data->callback)(module, call_data->user_data); + } + return (call_data->ret != 0); +} + static guint -prefs_module_list_foreach(GList *module_list, module_cb callback, +prefs_module_list_foreach(GTree *module_list, module_cb callback, gpointer user_data) { - GList *elem; - module_t *module; - guint ret; + call_foreach_t call_data; if (module_list == NULL) module_list = top_level_modules; - for (elem = g_list_first(module_list); elem != NULL; - elem = g_list_next(elem)) { - module = elem->data; - if (!module->obsolete) { - ret = (*callback)(module, user_data); - if (ret != 0) - return ret; - } - } - return 0; + call_data.callback = callback; + call_data.user_data = user_data; + call_data.ret = 0; + g_tree_foreach(module_list, call_foreach_cb, &call_data); + return call_data.ret; } /* @@ -480,7 +457,7 @@ prefs_module_list_foreach(GList *module_list, module_cb callback, */ gboolean prefs_module_has_submodules(module_t *module) { - return (module->submodules != NULL); + return (g_tree_nnodes(module->submodules) > 0); } /* @@ -513,18 +490,19 @@ prefs_modules_foreach_submodules(module_t *module, module_cb callback, gpointer return prefs_module_list_foreach((module)?module->submodules:top_level_modules, callback, user_data); } -static void -call_apply_cb(gpointer data, gpointer user_data _U_) +static gboolean +call_apply_cb(gpointer key _U_, gpointer value, gpointer data _U_) { - module_t *module = data; + module_t *module = value; if (module->obsolete) - return; + return FALSE; if (module->prefs_changed) { if (module->apply_cb != NULL) (*module->apply_cb)(); module->prefs_changed = FALSE; } + return FALSE; } /* @@ -536,7 +514,7 @@ call_apply_cb(gpointer data, gpointer user_data _U_) void prefs_apply_all(void) { - g_list_foreach(modules, call_apply_cb, NULL); + g_tree_foreach(modules, call_apply_cb, NULL); } /* @@ -549,7 +527,7 @@ void prefs_apply(module_t *module) { if (module && module->prefs_changed) - call_apply_cb(module, NULL); + call_apply_cb((gpointer)module->name, module, NULL); } /* @@ -2435,14 +2413,15 @@ write_pref(gpointer data, gpointer user_data) } } -static void -write_module_prefs(gpointer data, gpointer user_data) +static gboolean +write_module_prefs(gpointer key _U_, gpointer value, gpointer data) { write_pref_arg_t arg; - arg.module = data; - arg.pf = user_data; + arg.module = value; + arg.pf = data; g_list_foreach(arg.module->prefs, write_pref, &arg); + return FALSE; } /* Write out "prefs" to the user's preferences file, and return 0. @@ -2761,7 +2740,7 @@ write_prefs(char **pf_path_return) fprintf(pf, "\n####### Protocols ########\n"); - g_list_foreach(modules, write_module_prefs, pf); + g_tree_foreach(modules, write_module_prefs, pf); fclose(pf); diff --git a/epan/prefs.h b/epan/prefs.h index b0c3e2af60..c67b4fe07a 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -166,6 +166,12 @@ struct pref_module; typedef struct pref_module module_t; +/** Sets up memory used by proto routines. Called at program startup */ +extern void prefs_init(void); + +/** Frees memory used by proto routines. Called at program shutdown */ +extern void prefs_cleanup(void); + /* * Register a module that will have preferences. * Specify the module under which to register it or NULL to register it diff --git a/epan/proto.c b/epan/proto.c index 7933688fed..db4b3bc46c 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -343,8 +343,8 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data), proto_names = g_hash_table_new(g_int_hash, g_int_equal); - proto_short_names = g_hash_table_new(g_str_hash, g_str_equal); - proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal); + proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal); + proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal); proto_cleanup(); @@ -3503,7 +3503,7 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi */ key = g_malloc (sizeof(gint)); - *key = g_str_hash(name); + *key = wrs_str_hash(name); existing_name = g_hash_table_lookup(proto_names, key); if (existing_name != NULL) { /* g_error will terminate the program */ @@ -3548,7 +3548,7 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi protocol->is_enabled = TRUE; /* protocol is enabled by default */ protocol->can_toggle = TRUE; /* list will be sorted later by name, when all protocols completed registering */ - protocols = g_list_append(protocols, protocol); + protocols = g_list_prepend(protocols, protocol); /* Here we do allocate a new header_field_info struct */ hfinfo = g_mem_chunk_alloc(gmc_hfinfo); -- 2.34.1