optimization when freeing hash tables. some tuning of buffer allocations
* dict.c hash.c: optimization when freeing hash tables.
* parser.c xmlIO.c include/libxml/tree.h: some tuning of buffer
allocations
* parser.c parserInternals.c include/libxml/parser.h: keep a
single allocated block for all the attributes callbacks,
avoid useless malloc()/free()
* tree.c: do not realloc() when growing a buffer if the buffer
ain't full, malloc/memcpy/free avoid copying memory.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 2f46709..590df85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Tue Aug 19 16:54:18 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+ * dict.c hash.c: optimization when freeing hash tables.
+ * parser.c xmlIO.c include/libxml/tree.h: some tuning of buffer
+ allocations
+ * parser.c parserInternals.c include/libxml/parser.h: keep a
+ single allocated block for all the attributes callbacks,
+ avoid useless malloc()/free()
+ * tree.c: do not realloc() when growing a buffer if the buffer
+ ain't full, malloc/memcpy/free avoid copying memory.
+
Mon Aug 18 18:37:01 CEST 2003 Daniel Veillard <daniel@veillard.com>
* xmllint.c doc/xmllint.xml doc/xmllint.1: added option
diff --git a/dict.c b/dict.c
index 1002234..eaa4006 100644
--- a/dict.c
+++ b/dict.c
@@ -232,7 +232,7 @@
if (dict == NULL)
return;
if (dict->dict) {
- for(i = 0; i < dict->size; i++) {
+ for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
iter = &(dict->dict[i]);
if (iter->valid == 0)
continue;
@@ -243,6 +243,7 @@
xmlFree(iter->name);
if (!inside_dict)
xmlFree(iter);
+ dict->nbElems--;
inside_dict = 0;
iter = next;
}
diff --git a/hash.c b/hash.c
index 2a4d000..b4b8656 100644
--- a/hash.c
+++ b/hash.c
@@ -218,11 +218,13 @@
xmlHashEntryPtr iter;
xmlHashEntryPtr next;
int inside_table = 0;
+ int nbElems;
if (table == NULL)
return;
if (table->table) {
- for(i = 0; i < table->size; i++) {
+ nbElems = table->nbElems;
+ for(i = 0; (i < table->size) && (nbElems > 0); i++) {
iter = &(table->table[i]);
if (iter->valid == 0)
continue;
@@ -240,6 +242,7 @@
iter->payload = NULL;
if (!inside_table)
xmlFree(iter);
+ nbElems--;
inside_table = 0;
iter = next;
}
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index b080384..ac3f055 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -236,6 +236,8 @@
int recovery; /* run in recovery mode */
int progressive; /* is this a progressive parsing */
xmlDictPtr dict; /* dictionnary for the parser */
+ const xmlChar * *atts; /* array for the attributes callbacks */
+ int maxatts; /* the size of the array */
};
/**
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 4ca3c9a..b029ffc 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -50,7 +50,7 @@
*
* default buffer size 4000.
*/
-#define BASE_BUFFER_SIZE 4000
+#define BASE_BUFFER_SIZE 4096
/**
* XML_XML_NAMESPACE:
diff --git a/parser.c b/parser.c
index 535df1e..4eb5265 100644
--- a/parser.c
+++ b/parser.c
@@ -369,8 +369,8 @@
} while (0)
#define SHRINK if ((ctxt->progressive == 0) && \
- (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) && \
- (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \
+ (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
+ (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
xmlSHRINK (ctxt);
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
@@ -2363,6 +2363,7 @@
xmlChar limit = 0;
const xmlChar *in = NULL;
xmlChar *ret = NULL;
+
SHRINK;
GROW;
in = (xmlChar *) CUR_PTR;
@@ -2412,8 +2413,6 @@
xmlChar *current = NULL;
xmlEntityPtr ent;
-
- SHRINK;
if (NXT(0) == '"') {
ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
limit = '"';
@@ -6612,9 +6611,9 @@
const xmlChar *name;
const xmlChar *attname;
xmlChar *attvalue;
- const xmlChar **atts = NULL;
+ const xmlChar **atts = ctxt->atts;
int nbatts = 0;
- int maxatts = 0;
+ int maxatts = ctxt->maxatts;
int i;
if (RAW != '<') return(NULL);
@@ -6670,8 +6669,9 @@
* Add the pair to atts
*/
if (atts == NULL) {
- maxatts = 10;
- atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
+ maxatts = 22; /* allow for 10 attrs by default */
+ atts = (const xmlChar **)
+ xmlMalloc(maxatts * sizeof(xmlChar *));
if (atts == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc of %ld byte failed\n",
@@ -6683,12 +6683,14 @@
ctxt->disableSAX = 1;
goto failed;
}
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
} else if (nbatts + 4 > maxatts) {
const xmlChar **n;
maxatts *= 2;
n = (const xmlChar **) xmlRealloc((void *) atts,
- maxatts * sizeof(xmlChar *));
+ maxatts * sizeof(const xmlChar *));
if (n == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc of %ld byte failed\n",
@@ -6701,6 +6703,8 @@
goto failed;
}
atts = n;
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
}
atts[nbatts++] = attname;
atts[nbatts++] = attvalue;
@@ -6735,6 +6739,7 @@
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break;
}
+ SHRINK;
GROW;
}
@@ -6742,15 +6747,18 @@
* SAX: Start of Element !
*/
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
- (!ctxt->disableSAX))
- ctxt->sax->startElement(ctxt->userData, name, atts);
+ (!ctxt->disableSAX)) {
+ if (nbatts > 0)
+ ctxt->sax->startElement(ctxt->userData, name, atts);
+ else
+ ctxt->sax->startElement(ctxt->userData, name, NULL);
+ }
if (atts != NULL) {
/* Free only the content strings */
for (i = 1;i < nbatts;i+=2)
if (atts[i] != NULL)
xmlFree((xmlChar *) atts[i]);
- xmlFree((void *) atts);
}
return(name);
}
diff --git a/parserInternals.c b/parserInternals.c
index 5c85cbc..ea0a5d0 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -2218,6 +2218,8 @@
else
memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
+ ctxt->maxatts = 0;
+ ctxt->atts = NULL;
/* Allocate the Input stack */
ctxt->inputTab = (xmlParserInputPtr *)
xmlMalloc(5 * sizeof(xmlParserInputPtr));
@@ -2369,6 +2371,7 @@
xmlFree(ctxt->sax);
if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
+ if (ctxt->atts != NULL) xmlFree(ctxt->atts);
if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
#ifdef LIBXML_CATALOG_ENABLED
if (ctxt->catalogs != NULL)
diff --git a/tree.c b/tree.c
index 4dd1027..135c92b 100644
--- a/tree.c
+++ b/tree.c
@@ -6413,9 +6413,21 @@
if (buf->content == NULL)
rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
- else
+ else if (buf->size - buf->use < 100) {
rebuf = (xmlChar *) xmlRealloc(buf->content,
newSize * sizeof(xmlChar));
+ } else {
+ /*
+ * if we are reallocating a buffer far from being full, it's
+ * better to make a new allocation and copy only the used range
+ * and free the old one.
+ */
+ rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
+ if (rebuf != NULL) {
+ memcpy(rebuf, buf->content, buf->use);
+ xmlFree(buf->content);
+ }
+ }
if (rebuf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlBufferResize : out of memory!\n");
diff --git a/xmlIO.c b/xmlIO.c
index 715cec5..83907f9 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -1574,7 +1574,7 @@
return(NULL);
}
memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
- ret->buffer = xmlBufferCreate();
+ ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
if (ret->buffer == NULL) {
xmlFree(ret);
return(NULL);
@@ -1582,7 +1582,7 @@
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
ret->encoder = xmlGetCharEncodingHandler(enc);
if (ret->encoder != NULL)
- ret->raw = xmlBufferCreate();
+ ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
else
ret->raw = NULL;
ret->readcallback = NULL;
@@ -2173,16 +2173,15 @@
int buffree;
unsigned int needSize;
- if ((len <= MINLEN) && (len != 4))
+ if ((len <= MINLEN) && (len != 4))
len = MINLEN;
+
buffree = in->buffer->size - in->buffer->use;
if (buffree <= 0) {
xmlGenericError(xmlGenericErrorContext,
"xmlParserInputBufferGrow : buffer full !\n");
return(0);
}
- if (len > buffree)
- len = buffree;
needSize = in->buffer->use + len + 1;
if (needSize > in->buffer->size){