do string allocations in large pools, allowing to find if a string pertain
* dict.c include/libxml/dict.h: do string allocations in large
pools, allowing to find if a string pertain to a dict quickly
* xmllint.c: fix --stream --repeat --timing
* Makefile.am: the testThreads run output should be seen.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 6bf8561..1bb2fb9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Sep 17 01:07:56 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+ * dict.c include/libxml/dict.h: do string allocations in large
+ pools, allowing to find if a string pertain to a dict quickly
+ * xmllint.c: fix --stream --repeat --timing
+ * Makefile.am: the testThreads run output should be seen.
+
Mon Sep 15 16:46:28 CEST 2003 Daniel Veillard <daniel@veillard.com>
* SAX2.c include/libxml/parser.h: starting work on reusing the
diff --git a/Makefile.am b/Makefile.am
index 05bb587..6fd1879 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -566,10 +566,10 @@
@echo "##"
@echo "## Threaded regression tests"
@echo "##"
- -@($(CHECKER) $(top_builddir)/testThreads ; \
+ -($(CHECKER) $(top_builddir)/testThreads ; \
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";)
-Readertests : testReader$(EXEEXT)
+Readertests : xmllint$(EXEEXT)
@(echo > .memdump)
@echo "##"
@echo "## Reader regression tests"
diff --git a/dict.c b/dict.c
index 380e908..20d1efb 100644
--- a/dict.c
+++ b/dict.c
@@ -40,11 +40,21 @@
typedef xmlDictEntry *xmlDictEntryPtr;
struct _xmlDictEntry {
struct _xmlDictEntry *next;
- xmlChar *name;
+ const xmlChar *name;
int len;
int valid;
};
+typedef struct _xmlDictStrings xmlDictStrings;
+typedef xmlDictStrings *xmlDictStringsPtr;
+struct _xmlDictStrings {
+ xmlDictStringsPtr next;
+ xmlChar *free;
+ xmlChar *end;
+ int size;
+ int nbStrings;
+ xmlChar array[1];
+};
/*
* The entire dictionnary
*/
@@ -52,9 +62,59 @@
struct _xmlDictEntry *dict;
int size;
int nbElems;
+ xmlDictStringsPtr strings;
};
/*
+ * xmlDictAddString:
+ * @dict: the dictionnary
+ * @name: the name of the userdata
+ * @len: the length of the name, if -1 it is recomputed
+ *
+ * Add the string to the array[s]
+ *
+ * Returns the pointer of the local string, or NULL in case of error.
+ */
+static const xmlChar *
+xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
+ xmlDictStringsPtr pool;
+ const xmlChar *ret;
+ int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
+
+ pool = dict->strings;
+ while (pool != NULL) {
+ if (pool->end - pool->free > namelen)
+ goto found_pool;
+ if (pool->size > size) size = pool->size;
+ pool = pool->next;
+ }
+ /*
+ * Not found, need to allocate
+ */
+ if (pool == NULL) {
+ if (size == 0) size = 1000;
+ else size *= 4; /* exponential growth */
+ if (size < 4 * namelen)
+ size = 4 * namelen; /* just in case ! */
+ pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
+ if (pool == NULL)
+ return(NULL);
+ pool->size = size;
+ pool->nbStrings = 0;
+ pool->free = &pool->array[0];
+ pool->end = &pool->array[size];
+ pool->next = dict->strings;
+ dict->strings = pool;
+ }
+found_pool:
+ ret = pool->free;
+ memcpy(pool->free, name, namelen);
+ pool->free += namelen;
+ *(pool->free++) = 0;
+ return(ret);
+}
+
+/*
* xmlDictComputeKey:
* Calculate the hash key
*/
@@ -110,6 +170,7 @@
dict->size = MIN_DICT_SIZE;
dict->nbElems = 0;
dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
+ dict->strings = NULL;
if (dict->dict) {
memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
return(dict);
@@ -226,6 +287,7 @@
xmlDictEntryPtr iter;
xmlDictEntryPtr next;
int inside_dict = 0;
+ xmlDictStringsPtr pool, nextp;
if (dict == NULL)
return;
@@ -237,8 +299,6 @@
inside_dict = 1;
while (iter) {
next = iter->next;
- if (iter->name)
- xmlFree(iter->name);
if (!inside_dict)
xmlFree(iter);
dict->nbElems--;
@@ -249,6 +309,12 @@
}
xmlFree(dict->dict);
}
+ pool = dict->strings;
+ while (pool != NULL) {
+ nextp = pool->next;
+ xmlFree(pool);
+ pool = nextp;
+ }
xmlFree(dict);
}
@@ -294,6 +360,9 @@
return(insert->name);
}
+ ret = xmlDictAddString(dict, name, len);
+ if (ret == NULL)
+ return(NULL);
if (insert == NULL) {
entry = &(dict->dict[key]);
} else {
@@ -301,8 +370,7 @@
if (entry == NULL)
return(NULL);
}
-
- ret = entry->name = xmlStrndup(name, len);
+ entry->name = ret;
entry->len = len;
entry->next = NULL;
entry->valid = 1;
@@ -322,6 +390,30 @@
}
/**
+ * xmlDictOwns:
+ * @dict: the dictionnary
+ * @str: the string
+ *
+ * check if a string is owned by the disctionary
+ *
+ * Returns 1 if true, 0 if false and -1 in case of error
+ * -1 in case of error
+ */
+int
+xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
+ xmlDictStringsPtr pool;
+
+ if ((dict == NULL) || (str == NULL))
+ return(-1);
+ pool = dict->strings;
+ while (pool != NULL) {
+ if ((str >= pool->array) && (str <= pool->free))
+ return(1);
+ pool = pool->next;
+ }
+ return(0);
+}
+/**
* xmlDictSize:
* @dict: the dictionnary
*
diff --git a/include/libxml/dict.h b/include/libxml/dict.h
index 5b4a59a..551a7d8 100644
--- a/include/libxml/dict.h
+++ b/include/libxml/dict.h
@@ -47,6 +47,9 @@
xmlDictLookup (xmlDictPtr dict,
const xmlChar *name,
int len);
+XMLPUBFUN int XMLCALL
+ xmlDictOwns (xmlDictPtr dict,
+ const xmlChar *str);
XMLPUBFUN int XMLCALL
xmlDictSize (xmlDictPtr dict);
#ifdef __cplusplus
diff --git a/xmllint.c b/xmllint.c
index 1151bf7..21e3201 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -618,7 +618,7 @@
xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
#ifdef LIBXML_SCHEMAS_ENABLED
if (relaxng != NULL) {
- if (timing) {
+ if ((timing) && (!repeat)) {
startTimer();
}
ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
@@ -627,7 +627,7 @@
"Relax-NG schema %s failed to compile\n", relaxng);
relaxng = NULL;
}
- if (timing) {
+ if ((timing) && (!repeat)) {
endTimer("Compiling the schemas");
}
}
@@ -636,7 +636,7 @@
/*
* Process all nodes in sequence
*/
- if (timing) {
+ if ((timing) && (!repeat)) {
startTimer();
}
ret = xmlTextReaderRead(reader);
@@ -645,7 +645,7 @@
processNode(reader);
ret = xmlTextReaderRead(reader);
}
- if (timing) {
+ if ((timing) && (!repeat)) {
#ifdef LIBXML_SCHEMAS_ENABLED
if ((valid) || (relaxng != NULL))
#else