diff options
| author | 2016-05-12 02:32:55 +0200 | |
|---|---|---|
| committer | 2016-05-12 02:32:55 +0200 | |
| commit | 2af7318239c59555869d018bc355fe0e21d900c6 (patch) | |
| tree | 3b366f10c04d305c9bd72e31e28ca62596ba07dd | |
| parent | 6ab7e301f1854fd18891ddfeaa64e7485be990ba (diff) | |
| download | libplist-2af7318239c59555869d018bc355fe0e21d900c6.tar.gz libplist-2af7318239c59555869d018bc355fe0e21d900c6.tar.bz2 | |
bplist: Speed up plist_to_bin conversion for large plists
Using a better hashing algorithm and a larger hash table the conversion
is A LOT faster when processing large plists. Thanks to Xiao Deng for
reporting this issue and suggesting a fix.
| -rw-r--r-- | src/bplist.c | 11 | ||||
| -rw-r--r-- | src/hashtable.c | 8 | ||||
| -rw-r--r-- | src/hashtable.h | 2 |
3 files changed, 12 insertions, 9 deletions
diff --git a/src/bplist.c b/src/bplist.c index 3ba46a2..bb73b31 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -735,7 +735,7 @@ static unsigned int plist_data_hash(const void* key) | |||
| 735 | case PLIST_KEY: | 735 | case PLIST_KEY: |
| 736 | case PLIST_STRING: | 736 | case PLIST_STRING: |
| 737 | buff = data->strval; | 737 | buff = data->strval; |
| 738 | size = strlen(buff); | 738 | size = data->length; |
| 739 | break; | 739 | break; |
| 740 | case PLIST_DATA: | 740 | case PLIST_DATA: |
| 741 | case PLIST_ARRAY: | 741 | case PLIST_ARRAY: |
| @@ -752,9 +752,12 @@ static unsigned int plist_data_hash(const void* key) | |||
| 752 | break; | 752 | break; |
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | //now perform hash | 755 | // now perform hash using djb2 hashing algorithm |
| 756 | for (i = 0; i < size; buff++, i++) | 756 | // see: http://www.cse.yorku.ca/~oz/hash.html |
| 757 | hash = hash << 7 ^ (*buff); | 757 | hash += 5381; |
| 758 | for (i = 0; i < size; buff++, i++) { | ||
| 759 | hash = ((hash << 5) + hash) + *buff; | ||
| 760 | } | ||
| 758 | 761 | ||
| 759 | return hash; | 762 | return hash; |
| 760 | } | 763 | } |
diff --git a/src/hashtable.c b/src/hashtable.c index 08ff934..3568f3c 100644 --- a/src/hashtable.c +++ b/src/hashtable.c | |||
| @@ -24,7 +24,7 @@ hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func) | |||
| 24 | { | 24 | { |
| 25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); | 25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); |
| 26 | int i; | 26 | int i; |
| 27 | for (i = 0; i < 256; i++) { | 27 | for (i = 0; i < 4096; i++) { |
| 28 | ht->entries[i] = NULL; | 28 | ht->entries[i] = NULL; |
| 29 | } | 29 | } |
| 30 | ht->count = 0; | 30 | ht->count = 0; |
| @@ -38,7 +38,7 @@ void hash_table_destroy(hashtable_t *ht) | |||
| 38 | if (!ht) return; | 38 | if (!ht) return; |
| 39 | 39 | ||
| 40 | int i = 0; | 40 | int i = 0; |
| 41 | for (i = 0; i < 256; i++) { | 41 | for (i = 0; i < 4096; i++) { |
| 42 | if (ht->entries[i]) { | 42 | if (ht->entries[i]) { |
| 43 | hashentry_t* e = ht->entries[i]; | 43 | hashentry_t* e = ht->entries[i]; |
| 44 | while (e) { | 44 | while (e) { |
| @@ -58,7 +58,7 @@ void hash_table_insert(hashtable_t* ht, void *key, void *value) | |||
| 58 | 58 | ||
| 59 | unsigned int hash = ht->hash_func(key); | 59 | unsigned int hash = ht->hash_func(key); |
| 60 | 60 | ||
| 61 | int idx0 = hash & 0xFF; | 61 | int idx0 = hash & 0xFFF; |
| 62 | 62 | ||
| 63 | // get the idx0 list | 63 | // get the idx0 list |
| 64 | hashentry_t* e = ht->entries[idx0]; | 64 | hashentry_t* e = ht->entries[idx0]; |
| @@ -93,7 +93,7 @@ void* hash_table_lookup(hashtable_t* ht, void *key) | |||
| 93 | if (!ht || !key) return NULL; | 93 | if (!ht || !key) return NULL; |
| 94 | unsigned int hash = ht->hash_func(key); | 94 | unsigned int hash = ht->hash_func(key); |
| 95 | 95 | ||
| 96 | int idx0 = hash & 0xFF; | 96 | int idx0 = hash & 0xFFF; |
| 97 | 97 | ||
| 98 | hashentry_t* e = ht->entries[idx0]; | 98 | hashentry_t* e = ht->entries[idx0]; |
| 99 | while (e) { | 99 | while (e) { |
diff --git a/src/hashtable.h b/src/hashtable.h index c28de91..60a40ab 100644 --- a/src/hashtable.h +++ b/src/hashtable.h | |||
| @@ -32,7 +32,7 @@ typedef unsigned int(*hash_func_t)(const void* key); | |||
| 32 | typedef int (*compare_func_t)(const void *a, const void *b); | 32 | typedef int (*compare_func_t)(const void *a, const void *b); |
| 33 | 33 | ||
| 34 | typedef struct hashtable_t { | 34 | typedef struct hashtable_t { |
| 35 | hashentry_t *entries[256]; | 35 | hashentry_t *entries[4096]; |
| 36 | size_t count; | 36 | size_t count; |
| 37 | hash_func_t hash_func; | 37 | hash_func_t hash_func; |
| 38 | compare_func_t compare_func; | 38 | compare_func_t compare_func; |
