]> git.sesse.net Git - vlc/commitdiff
Sort configuration items for faster lookup
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 23 Jan 2010 21:00:31 +0000 (23:00 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Sat, 23 Jan 2010 21:03:43 +0000 (23:03 +0200)
We have well over one thousand configuration items, not counting
dummy hint entries. So now, sort all of them once (well, twice),
and use binary instead of linear search for lookups.
config_Get*, config_Put*, var_Create(with INHERIT flag),
var_CreateGet* and var_Inherit* do such lookups.

src/config/configuration.h
src/config/core.c
src/modules/modules.c

index a419552e84335c9034008cb7f55b832490a08d09..c16d08e695b824b79c92c1d6aeb87c72b02f9088 100644 (file)
@@ -41,6 +41,8 @@ void config_Free( module_t * );
 
 int __config_LoadCmdLine   ( vlc_object_t *, int *, const char *[], bool );
 int __config_LoadConfigFile( vlc_object_t *, const char * );
+int config_SortConfig (void);
+void config_UnsortConfig (void);
 
 char *config_GetDataDirDefault( void );
 
index a8ffd53082968ff45ca3aea52ce37b2fa40789ce..19cd370d0675a4c9ea1f56471f8c2a4cf9087dc9 100644 (file)
@@ -400,50 +400,97 @@ void __config_PutFloat( vlc_object_t *p_this,
     }
 }
 
-/*****************************************************************************
- * config_FindConfig: find the config structure associated with an option.
- *****************************************************************************
- * FIXME: This function really needs to be optimized.
- * FIXME: And now even more.
- * FIXME: remove p_this pointer parameter (or use it)
- *****************************************************************************/
-module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
+static int confcmp (const void *a, const void *b)
 {
-    VLC_UNUSED(p_this);
-    module_t *p_parser;
+    const module_config_t *const *ca = a, *const *cb = b;
 
-    if( !psz_name ) return NULL;
+    return strcmp ((*ca)->psz_name, (*cb)->psz_name);
+}
 
-    module_t **list = module_list_get (NULL);
-    if (list == NULL)
-        return NULL;
+static int confnamecmp (const void *key, const void *elem)
+{
+    const module_config_t *const *conf = elem;
 
-    for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
+    return strcmp (key, (*conf)->psz_name);
+}
+
+static struct
+{
+    module_config_t **list;
+    size_t count;
+} config = { NULL, 0 };
+
+/**
+ * Index the configuration items by name for faster lookups.
+ */
+int config_SortConfig (void)
+{
+    size_t nmod;
+    module_t **mlist = module_list_get (&nmod);
+    if (unlikely(mlist == NULL))
+        return VLC_ENOMEM;
+
+    size_t nconf = 0;
+    for (size_t i = 0; i < nmod; i++)
+         nconf  += mlist[i]->confsize;
+
+    module_config_t **clist = malloc (sizeof (*clist) * nconf);
+    if (unlikely(clist == NULL))
     {
-        module_config_t *p_item, *p_end;
+        module_list_free (mlist);
+        return VLC_ENOMEM;
+    }
 
-        if( !p_parser->i_config_items )
-            continue;
+    nconf = 0;
+    for (size_t i = 0; i < nmod; i++)
+    {
+        module_t *parser = mlist[i];
+        module_config_t *item, *end;
 
-        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
-             p_item < p_end;
-             p_item++ )
+        for (item = parser->p_config, end = item + parser->confsize;
+             item < end;
+             item++)
         {
-            if( p_item->i_type & CONFIG_HINT )
-                /* ignore hints */
-                continue;
-            if( !strcmp( psz_name, p_item->psz_name )
-             || ( p_item->psz_oldname
-              && !strcmp( psz_name, p_item->psz_oldname ) ) )
-            {
-                module_list_free (list);
-                return p_item;
-            }
+            if (item->i_type & CONFIG_HINT)
+                continue; /* ignore hints */
+            clist[nconf++] = item;
         }
     }
+    module_list_free (mlist);
 
-    module_list_free (list);
-    return NULL;
+    qsort (clist, nconf, sizeof (*clist), confcmp);
+
+    config.list = clist;
+    config.count = nconf;
+    return VLC_SUCCESS;
+}
+
+void config_UnsortConfig (void)
+{
+    module_config_t **clist;
+
+    clist = config.list;
+    config.list = NULL;
+    config.count = 0;
+
+    free (config.list);
+}
+
+/*****************************************************************************
+ * config_FindConfig: find the config structure associated with an option.
+ *****************************************************************************
+ * FIXME: remove p_this pointer parameter (or use it)
+ *****************************************************************************/
+module_config_t *config_FindConfig (vlc_object_t *p_this, const char *name)
+{
+    VLC_UNUSED(p_this);
+
+    if (unlikely(name == NULL))
+        return NULL;
+
+    module_config_t *const *p;
+    p = bsearch (name, config.list, config.count, sizeof (*p), confnamecmp);
+    return p ? *p : NULL;
 }
 
 /*****************************************************************************
index c1bf56f040e9cf2e913bfb6ecf7b8083cd94b3b3..23e4bde234d2ce03559f2d78c09f3e54819f0d54 100644 (file)
@@ -138,6 +138,7 @@ void __module_InitBank( vlc_object_t *p_this )
          * as for every other module. */
         AllocateBuiltinModule( p_this, vlc_entry__main );
         vlc_rwlock_init (&config_lock);
+        config_SortConfig ();
     }
     else
         p_module_bank->i_usage++;
@@ -181,6 +182,8 @@ void module_EndBank( vlc_object_t *p_this, bool b_plugins )
         vlc_mutex_unlock( &module_lock );
         return;
     }
+
+    config_UnsortConfig ();
     vlc_rwlock_destroy (&config_lock);
     p_module_bank = NULL;
     vlc_mutex_unlock( &module_lock );
@@ -237,6 +240,8 @@ void module_LoadPlugins( vlc_object_t * p_this, bool b_cache_delete )
         if( p_module_bank->b_cache || b_cache_delete )
             CacheLoad( p_this, p_module_bank, b_cache_delete );
         AllocateAllPlugins( p_this, p_module_bank );
+        config_UnsortConfig ();
+        config_SortConfig ();
     }
 #endif
     vlc_mutex_unlock( &module_lock );