diff options
author | Nick Wellnhofer <wellnhofer@aevum.de> | 2019-06-19 14:00:26 +0200 |
---|---|---|
committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2019-06-19 14:15:02 +0200 |
commit | 9216d4e5102d257513c39a7f816d2bfbaa5a89e4 (patch) | |
tree | 0917dce2ab1585a90d5afcbd2197216828f9d808 | |
parent | 5b0965010abf274f7a3a1291d16dde34c167e8a7 (diff) | |
download | libxslt-9216d4e5102d257513c39a7f816d2bfbaa5a89e4.tar.gz |
Fix performance regression with xsl:number
Commit a846514a disabled the pattern matching cache completely for
`count` and `from` patterns of xsl:number instructions. This caused a
huge performance regression for large documents.
Revert the commit and clear the cache after evaluating an xsl:number.
Closes #16.
-rw-r--r-- | doc/symbols.xml | 1 | ||||
-rw-r--r-- | libxslt/libxslt.syms | 3 | ||||
-rw-r--r-- | libxslt/numbers.c | 10 | ||||
-rw-r--r-- | libxslt/pattern.c | 26 | ||||
-rw-r--r-- | libxslt/pattern.h | 3 |
5 files changed, 39 insertions, 4 deletions
diff --git a/doc/symbols.xml b/doc/symbols.xml index 502a966d..860b2bbd 100644 --- a/doc/symbols.xml +++ b/doc/symbols.xml @@ -321,5 +321,6 @@ </release> <release version="1.1.34"> <symbol file="xsltInternals">xsltParseStylesheetUser</symbol> + <symbol file="pattern">xsltCompMatchClearCache</symbol> </release> </symbols> diff --git a/libxslt/libxslt.syms b/libxslt/libxslt.syms index 07c0a660..94b1d8aa 100644 --- a/libxslt/libxslt.syms +++ b/libxslt/libxslt.syms @@ -504,5 +504,8 @@ LIBXML2_1.1.34 { # xsltInternals xsltParseStylesheetUser; + +# pattern + xsltCompMatchClearCache; } LIBXML2_1.1.30; diff --git a/libxslt/numbers.c b/libxslt/numbers.c index 0a2a51cb..f1ed8846 100644 --- a/libxslt/numbers.c +++ b/libxslt/numbers.c @@ -829,6 +829,16 @@ xsltNumberFormat(xsltTransformContextPtr ctxt, output); } } + + /* + * Unlike `match` patterns, `count` and `from` patterns can contain + * variable references, so we have to clear the pattern match + * cache if the "direct" matching algorithm was used. + */ + if (data->countPat != NULL) + xsltCompMatchClearCache(ctxt, data->countPat); + if (data->fromPat != NULL) + xsltCompMatchClearCache(ctxt, data->fromPat); } /* Insert number as text node */ xsltCopyTextString(ctxt, ctxt->insert, xmlBufferContent(output), 0); diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 32de1b48..fc52b88c 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -113,7 +113,6 @@ struct _xsltCompMatch { xmlNsPtr *nsList; /* the namespaces in scope */ int nsNr; /* the number of namespaces in scope */ xsltStepOpPtr steps; /* ops for computation */ - int novar; /* doesn't contain variables */ }; typedef struct _xsltParserContext xsltParserContext; @@ -589,8 +588,7 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, } ix = 0; - if ((parent == NULL) || (node->doc == NULL) || isRVT || - (comp->novar == 0)) + if ((parent == NULL) || (node->doc == NULL) || isRVT) nocache = 1; if (nocache == 0) { @@ -1245,6 +1243,27 @@ xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, return(0); } +void +xsltCompMatchClearCache(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp) { + xsltStepOpPtr sel; + xmlXPathObjectPtr list; + + if ((ctxt == NULL) || (comp == NULL)) + return; + + sel = &comp->steps[0]; + list = (xmlXPathObjectPtr) XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra); + + if (list != NULL) { + xmlXPathFreeObject(list); + + XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = NULL; + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = NULL; + XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = 0; + XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) = NULL; + } +} + /************************************************************************ * * * Dedicated parser for templates * @@ -1966,7 +1985,6 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc, j++; } element->nsNr = j; - element->novar = novar; #ifdef WITH_XSLT_DEBUG_PATTERN diff --git a/libxslt/pattern.h b/libxslt/pattern.h index eb21be32..a0991c0c 100644 --- a/libxslt/pattern.h +++ b/libxslt/pattern.h @@ -45,6 +45,9 @@ XSLTPUBFUN int XSLTCALL xmlNodePtr node, xsltCompMatchPtr comp); XSLTPUBFUN void XSLTCALL + xsltCompMatchClearCache (xsltTransformContextPtr ctxt, + xsltCompMatchPtr comp); +XSLTPUBFUN void XSLTCALL xsltNormalizeCompSteps (void *payload, void *data, const xmlChar *name); |