1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-01-26 10:03:34 +03:00

dict: Tune hash table growth

Introduce load factor as main trigger and increase MAX_HASH_LEN. This
should make growth behavior more predictable.

Raise size limit to INT_MAX. This avoids quadratic behavior with larger
tables.
This commit is contained in:
Nick Wellnhofer 2023-09-01 14:51:55 +02:00
parent 4b8f7cf05d
commit 6d7aaaa835
2 changed files with 36 additions and 23 deletions

33
dict.c
View File

@ -60,9 +60,10 @@ typedef unsigned __int32 uint32_t;
/* #define DEBUG_GROW */
/* #define DICT_DEBUG_PATTERNS */
#define MAX_HASH_LEN 3
#define MAX_HASH_LEN 16
#define MAX_FILL 2
#define GROWTH_FACTOR 4
#define MIN_DICT_SIZE 128
#define MAX_DICT_HASH 100000000
#define WITH_BIG_KEY
#ifdef WITH_BIG_KEY
@ -654,16 +655,14 @@ xmlDictGrow(xmlDictPtr dict, size_t size) {
if (dict == NULL)
return(-1);
if (size < 8)
return(-1);
if (size > MAX_DICT_HASH)
return(-1);
oldsize = dict->size;
if (size <= oldsize)
return(0);
#ifdef DICT_DEBUG_PATTERNS
fprintf(stderr, "*");
#endif
oldsize = dict->size;
olddict = dict->dict;
if (olddict == NULL)
return(-1);
@ -954,9 +953,12 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
dict->nbElems++;
if ((nbi > MAX_HASH_LEN) &&
(dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
if ((dict->nbElems > dict->size / MAX_FILL) ||
(nbi > MAX_HASH_LEN)) {
int newSize = dict->size > INT_MAX / GROWTH_FACTOR ?
INT_MAX :
GROWTH_FACTOR * dict->size;
if (xmlDictGrow(dict, newSize) != 0)
return(NULL);
}
/* Note that entry may have been freed at this point by xmlDictGrow */
@ -1167,9 +1169,14 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
dict->nbElems++;
if ((nbi > MAX_HASH_LEN) &&
(dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
if ((dict->nbElems > dict->size / MAX_FILL) ||
(nbi > MAX_HASH_LEN)) {
int newSize = dict->size > INT_MAX / GROWTH_FACTOR ?
INT_MAX :
GROWTH_FACTOR * dict->size;
if (xmlDictGrow(dict, newSize) != 0)
return(NULL);
}
/* Note that entry may have been freed at this point by xmlDictGrow */
return(ret);

26
hash.c
View File

@ -41,7 +41,10 @@
#include "private/dict.h"
#define MAX_HASH_LEN 8
#define MAX_HASH_LEN 16
#define MAX_FILL 2
#define GROWTH_FACTOR 4
#define MIN_HASH_SIZE 16
/* #define DEBUG_GROW */
@ -182,8 +185,8 @@ xmlHashCreate(int size) {
xmlInitParser();
if (size <= 0)
size = 256;
if (size <= MIN_HASH_SIZE)
size = MIN_HASH_SIZE;
table = xmlMalloc(sizeof(xmlHashTable));
if (table) {
@ -245,12 +248,10 @@ xmlHashGrow(xmlHashTablePtr table, int size) {
if (table == NULL)
return(-1);
if (size < 8)
return(-1);
if (size > 8 * 2048)
return(-1);
oldsize = table->size;
if (size <= oldsize)
return(0);
oldtable = table->table;
if (oldtable == NULL)
return(-1);
@ -644,8 +645,13 @@ xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
table->nbElems++;
if (len > MAX_HASH_LEN)
xmlHashGrow(table, MAX_HASH_LEN * table->size);
if ((table->nbElems > table->size / MAX_FILL) ||
(len > MAX_HASH_LEN)) {
int newSize = table->size > INT_MAX / GROWTH_FACTOR ?
INT_MAX :
GROWTH_FACTOR * table->size;
xmlHashGrow(table, newSize);
}
return(0);