1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-29 11:41:22 +03:00

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
This commit is contained in:
Daniel Veillard
2003-08-19 15:01:28 +00:00
parent 66f68e716b
commit 6155d8aafa
9 changed files with 60 additions and 21 deletions

View File

@ -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> Mon Aug 18 18:37:01 CEST 2003 Daniel Veillard <daniel@veillard.com>
* xmllint.c doc/xmllint.xml doc/xmllint.1: added option * xmllint.c doc/xmllint.xml doc/xmllint.1: added option

3
dict.c
View File

@ -232,7 +232,7 @@ xmlDictFree(xmlDictPtr dict) {
if (dict == NULL) if (dict == NULL)
return; return;
if (dict->dict) { if (dict->dict) {
for(i = 0; i < dict->size; i++) { for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
iter = &(dict->dict[i]); iter = &(dict->dict[i]);
if (iter->valid == 0) if (iter->valid == 0)
continue; continue;
@ -243,6 +243,7 @@ xmlDictFree(xmlDictPtr dict) {
xmlFree(iter->name); xmlFree(iter->name);
if (!inside_dict) if (!inside_dict)
xmlFree(iter); xmlFree(iter);
dict->nbElems--;
inside_dict = 0; inside_dict = 0;
iter = next; iter = next;
} }

5
hash.c
View File

@ -218,11 +218,13 @@ xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
xmlHashEntryPtr iter; xmlHashEntryPtr iter;
xmlHashEntryPtr next; xmlHashEntryPtr next;
int inside_table = 0; int inside_table = 0;
int nbElems;
if (table == NULL) if (table == NULL)
return; return;
if (table->table) { 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]); iter = &(table->table[i]);
if (iter->valid == 0) if (iter->valid == 0)
continue; continue;
@ -240,6 +242,7 @@ xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) {
iter->payload = NULL; iter->payload = NULL;
if (!inside_table) if (!inside_table)
xmlFree(iter); xmlFree(iter);
nbElems--;
inside_table = 0; inside_table = 0;
iter = next; iter = next;
} }

View File

@ -236,6 +236,8 @@ struct _xmlParserCtxt {
int recovery; /* run in recovery mode */ int recovery; /* run in recovery mode */
int progressive; /* is this a progressive parsing */ int progressive; /* is this a progressive parsing */
xmlDictPtr dict; /* dictionnary for the parser */ xmlDictPtr dict; /* dictionnary for the parser */
const xmlChar * *atts; /* array for the attributes callbacks */
int maxatts; /* the size of the array */
}; };
/** /**

View File

@ -50,7 +50,7 @@ typedef xmlEntity *xmlEntityPtr;
* *
* default buffer size 4000. * default buffer size 4000.
*/ */
#define BASE_BUFFER_SIZE 4000 #define BASE_BUFFER_SIZE 4096
/** /**
* XML_XML_NAMESPACE: * XML_XML_NAMESPACE:

View File

@ -369,8 +369,8 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
} while (0) } while (0)
#define SHRINK if ((ctxt->progressive == 0) && \ #define SHRINK if ((ctxt->progressive == 0) && \
(ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) && \ (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
(ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
xmlSHRINK (ctxt); xmlSHRINK (ctxt);
static void xmlSHRINK (xmlParserCtxtPtr ctxt) { static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
@ -2363,6 +2363,7 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) {
xmlChar limit = 0; xmlChar limit = 0;
const xmlChar *in = NULL; const xmlChar *in = NULL;
xmlChar *ret = NULL; xmlChar *ret = NULL;
SHRINK; SHRINK;
GROW; GROW;
in = (xmlChar *) CUR_PTR; in = (xmlChar *) CUR_PTR;
@ -2412,8 +2413,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt) {
xmlChar *current = NULL; xmlChar *current = NULL;
xmlEntityPtr ent; xmlEntityPtr ent;
SHRINK;
if (NXT(0) == '"') { if (NXT(0) == '"') {
ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
limit = '"'; limit = '"';
@ -6612,9 +6611,9 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
const xmlChar *name; const xmlChar *name;
const xmlChar *attname; const xmlChar *attname;
xmlChar *attvalue; xmlChar *attvalue;
const xmlChar **atts = NULL; const xmlChar **atts = ctxt->atts;
int nbatts = 0; int nbatts = 0;
int maxatts = 0; int maxatts = ctxt->maxatts;
int i; int i;
if (RAW != '<') return(NULL); if (RAW != '<') return(NULL);
@ -6670,8 +6669,9 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
* Add the pair to atts * Add the pair to atts
*/ */
if (atts == NULL) { if (atts == NULL) {
maxatts = 10; maxatts = 22; /* allow for 10 attrs by default */
atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *)); atts = (const xmlChar **)
xmlMalloc(maxatts * sizeof(xmlChar *));
if (atts == NULL) { if (atts == NULL) {
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"malloc of %ld byte failed\n", "malloc of %ld byte failed\n",
@ -6683,12 +6683,14 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
ctxt->disableSAX = 1; ctxt->disableSAX = 1;
goto failed; goto failed;
} }
ctxt->atts = atts;
ctxt->maxatts = maxatts;
} else if (nbatts + 4 > maxatts) { } else if (nbatts + 4 > maxatts) {
const xmlChar **n; const xmlChar **n;
maxatts *= 2; maxatts *= 2;
n = (const xmlChar **) xmlRealloc((void *) atts, n = (const xmlChar **) xmlRealloc((void *) atts,
maxatts * sizeof(xmlChar *)); maxatts * sizeof(const xmlChar *));
if (n == NULL) { if (n == NULL) {
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"realloc of %ld byte failed\n", "realloc of %ld byte failed\n",
@ -6701,6 +6703,8 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
goto failed; goto failed;
} }
atts = n; atts = n;
ctxt->atts = atts;
ctxt->maxatts = maxatts;
} }
atts[nbatts++] = attname; atts[nbatts++] = attname;
atts[nbatts++] = attvalue; atts[nbatts++] = attvalue;
@ -6735,6 +6739,7 @@ failed:
if (ctxt->recovery == 0) ctxt->disableSAX = 1; if (ctxt->recovery == 0) ctxt->disableSAX = 1;
break; break;
} }
SHRINK;
GROW; GROW;
} }
@ -6742,15 +6747,18 @@ failed:
* SAX: Start of Element ! * SAX: Start of Element !
*/ */
if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) && if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
(!ctxt->disableSAX)) (!ctxt->disableSAX)) {
ctxt->sax->startElement(ctxt->userData, name, atts); if (nbatts > 0)
ctxt->sax->startElement(ctxt->userData, name, atts);
else
ctxt->sax->startElement(ctxt->userData, name, NULL);
}
if (atts != NULL) { if (atts != NULL) {
/* Free only the content strings */ /* Free only the content strings */
for (i = 1;i < nbatts;i+=2) for (i = 1;i < nbatts;i+=2)
if (atts[i] != NULL) if (atts[i] != NULL)
xmlFree((xmlChar *) atts[i]); xmlFree((xmlChar *) atts[i]);
xmlFree((void *) atts);
} }
return(name); return(name);
} }

View File

@ -2218,6 +2218,8 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
else else
memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler)); memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
ctxt->maxatts = 0;
ctxt->atts = NULL;
/* Allocate the Input stack */ /* Allocate the Input stack */
ctxt->inputTab = (xmlParserInputPtr *) ctxt->inputTab = (xmlParserInputPtr *)
xmlMalloc(5 * sizeof(xmlParserInputPtr)); xmlMalloc(5 * sizeof(xmlParserInputPtr));
@ -2369,6 +2371,7 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
xmlFree(ctxt->sax); xmlFree(ctxt->sax);
if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory); if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab); if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
if (ctxt->atts != NULL) xmlFree(ctxt->atts);
if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
#ifdef LIBXML_CATALOG_ENABLED #ifdef LIBXML_CATALOG_ENABLED
if (ctxt->catalogs != NULL) if (ctxt->catalogs != NULL)

14
tree.c
View File

@ -6413,9 +6413,21 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
if (buf->content == NULL) if (buf->content == NULL)
rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar)); rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
else else if (buf->size - buf->use < 100) {
rebuf = (xmlChar *) xmlRealloc(buf->content, rebuf = (xmlChar *) xmlRealloc(buf->content,
newSize * sizeof(xmlChar)); 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) { if (rebuf == NULL) {
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"xmlBufferResize : out of memory!\n"); "xmlBufferResize : out of memory!\n");

View File

@ -1574,7 +1574,7 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
return(NULL); return(NULL);
} }
memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
ret->buffer = xmlBufferCreate(); ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
if (ret->buffer == NULL) { if (ret->buffer == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
@ -1582,7 +1582,7 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
ret->encoder = xmlGetCharEncodingHandler(enc); ret->encoder = xmlGetCharEncodingHandler(enc);
if (ret->encoder != NULL) if (ret->encoder != NULL)
ret->raw = xmlBufferCreate(); ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize);
else else
ret->raw = NULL; ret->raw = NULL;
ret->readcallback = NULL; ret->readcallback = NULL;
@ -2175,14 +2175,13 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
if ((len <= MINLEN) && (len != 4)) if ((len <= MINLEN) && (len != 4))
len = MINLEN; len = MINLEN;
buffree = in->buffer->size - in->buffer->use; buffree = in->buffer->size - in->buffer->use;
if (buffree <= 0) { if (buffree <= 0) {
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"xmlParserInputBufferGrow : buffer full !\n"); "xmlParserInputBufferGrow : buffer full !\n");
return(0); return(0);
} }
if (len > buffree)
len = buffree;
needSize = in->buffer->use + len + 1; needSize = in->buffer->use + len + 1;
if (needSize > in->buffer->size){ if (needSize > in->buffer->size){