[vlc-devel] [PATCH] vlc_arrays: force hash table sizes to prime numbers

Francois Cartegnie fcvlcdev at free.fr
Tue Aug 11 21:00:58 CEST 2020


Our performance is really bad on hash collision/realloc.

Sizing with prime numbers has the property of creating a 
better distribution (as well as not being close to 2^n).

We also can increase the chained list depth.

This had limited testing and will need unit tests.

Francois


---
 include/vlc_arrays.h | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/include/vlc_arrays.h b/include/vlc_arrays.h
index b558422f93..acc940f32f 100644
--- a/include/vlc_arrays.h
+++ b/include/vlc_arrays.h
@@ -411,10 +411,32 @@ typedef struct vlc_dictionary_t
 
 static void * const kVLCDictionaryNotFound = NULL;
 
-static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
+/* try to have prime numbers to avoid collisions */
+static const int vlc_dictionary_sizes[12] = { 0, 3, 7, 17, 29, 61, 113, 173, 233, 331, 491, 757 };
+
+static inline int vlc_dictionary_alignsize( int i_size )
 {
-    p_dict->p_entries = NULL;
+    for( int i=0 ; i<12; i++ )
+    {
+        if(i_size <= vlc_dictionary_sizes[i])
+            return vlc_dictionary_sizes[i];
+    }
+    return i_size;
+}
 
+static inline int vlc_dictionary_growsize( int i_oldsize )
+{
+    for( int i=0 ; i<11; i++ )
+    {
+        if(i_oldsize == vlc_dictionary_sizes[i])
+            return vlc_dictionary_sizes[i+1];
+    }
+    return (i_oldsize + 2) * 3 / 2;
+}
+
+static inline void vlc_dictionary_init_impl_( vlc_dictionary_t * p_dict, int i_size )
+{
+    p_dict->p_entries = NULL;
     if( i_size > 0 )
     {
         p_dict->p_entries = (vlc_dictionary_entry_t **)calloc( i_size, sizeof(*p_dict->p_entries) );
@@ -424,6 +446,12 @@ static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
     p_dict->i_size = i_size;
 }
 
+static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
+{
+    i_size = vlc_dictionary_alignsize( i_size );
+    vlc_dictionary_init_impl_( p_dict, i_size );
+}
+
 static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict,
                                          void ( * pf_free )( void * p_data, void * p_obj ),
                                          void * p_obj )
@@ -540,7 +568,7 @@ vlc_dictionary_insert_impl_( vlc_dictionary_t * p_dict, const char * psz_key,
                              void * p_value, bool rebuild )
 {
     if( !p_dict->p_entries )
-        vlc_dictionary_init( p_dict, 1 );
+        vlc_dictionary_init( p_dict, 3 );
 
     int i_pos = DictHash( psz_key, p_dict->i_size );
     vlc_dictionary_entry_t * p_entry;
@@ -560,9 +588,9 @@ vlc_dictionary_insert_impl_( vlc_dictionary_t * p_dict, const char * psz_key,
         {
             /* Here it starts to be not good, rebuild a bigger dictionary */
             struct vlc_dictionary_t new_dict;
-            int i_new_size = ( (p_dict->i_size+2) * 3) / 2; /* XXX: this need tuning */
+            int i_new_size = vlc_dictionary_growsize( p_dict->i_size );
             int i;
-            vlc_dictionary_init( &new_dict, i_new_size );
+            vlc_dictionary_init_impl_( &new_dict, i_new_size );
             for( i = 0; i < p_dict->i_size; i++ )
             {
                 p_entry = p_dict->p_entries[i];
-- 
2.25.4



More information about the vlc-devel mailing list