[libxslt] Fix performance regression with xsl:number



commit 9216d4e5102d257513c39a7f816d2bfbaa5a89e4
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Wed Jun 19 14:00:26 2019 +0200

    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.

 doc/symbols.xml      |  1 +
 libxslt/libxslt.syms |  3 +++
 libxslt/numbers.c    | 10 ++++++++++
 libxslt/pattern.c    | 26 ++++++++++++++++++++++----
 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
@@ -44,6 +44,9 @@ XSLTPUBFUN int XSLTCALL
                xsltTestCompMatchList   (xsltTransformContextPtr ctxt,
                                         xmlNodePtr node,
                                         xsltCompMatchPtr comp);
+XSLTPUBFUN void XSLTCALL
+               xsltCompMatchClearCache (xsltTransformContextPtr ctxt,
+                                        xsltCompMatchPtr comp);
 XSLTPUBFUN void XSLTCALL
                xsltNormalizeCompSteps  (void *payload,
                                         void *data,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]