Я хочу улучшить производительность xslt

У меня есть платформа, которая генерирует XML, на основе Запроса HTTP и текущего состояния сеанса. Я могу протестировать в HTML, но выпуск продукции будет VXML - возможно, одна или две "разновидности" по разным причинам.

Вот медленная часть моего HttpServlet:

jsp InputStream ms = new java.io.ByteArrayInputStream(sb.toString().getBytes());
Source xmlSource = new javax.xml.transform.stream.StreamSource(ms);
String filePath = getServletContext().getRealPath(("/GetNextEvent-").
        concat(req.getSession().getAttribute("client").toString().toUpperCase()).concat(".xsl"));
Source xsltSource = new javax.xml.transform.stream.StreamSource(filePath);
Result result = new javax.xml.transform.stream.StreamResult(resp.getWriter());
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer(xsltSource);
t.transform(xmlSource, result);

Это в настоящее время берет ~ 200 мс. Я хотел бы за него быть намного более быстрым. Возможно <10 мс?

  1. Предложения для кэширования? - видящий, что xsl файлы остаются такими же в течение развертывания, объекты Преобразователя могут кэшироваться неограниченно долго. Я думаю о кэшировании его на Сеансовом уровне, таким образом, каждая сессия (одновременные 1000-е) имеет их собственное. Какие-либо предложения? Я должен использовать какие-либо платформы для кэширования по какой-либо причине?
  2. Существует ли более быстрый способ преобразовать xml к ответному потоку?
  3. Я должен фрагментировать это и пойти другим путем? Если Вы заметили sb.toString, я использую StringBuilder для получения представления XML объектов (объекты используют stringbuilder для создания строки XML). Требуется приблизительно 1 миллисекунда для создания XML-документа с помощью StringBuilders, таким образом, я не обеспокоен этим в данный момент.

Править:

Вот документ XSL. XML-документ является обычно очень маленьким. Просто несколько элементов. Образец XML ниже XSL:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regexp="http://exslt.org/regular-expressions"
    xmlns:str="http://exslt.org/strings" xmlns:twc="http://twc.com/2009/01/ivr/framework"
    exclude-result-prefixes="twc regexp str" extension-element-prefixes="str">
    <xsl:output method="xml" encoding="ISO-8859-1" />
    <xsl:template match="/">
        <vxml xmlns="http://www.w3.org/2001/vxml" version="2.1" xml:lang="en-US"
            application="root.xml">
            <xsl:attribute name="xml:lang"><xsl:value-of
                select="//twc:response/@language" /></xsl:attribute>
            <form id="ivrFramework">
                <var name="logDebug">
                    <xsl:attribute name="expr"><xsl:value-of
                        select="//twc:response/@debug" /></xsl:attribute>
                </var>
                <var name="event" expr="'OK'" />
                <var name="lastResult" expr="''" />
                <var name="lastResultMode" expr="''" />
                <var name="lastResultValue" expr="''" />
                <var name="srConfidence" expr="'1000'" />

                <xsl:apply-templates select="//twc:command" />
                <xsl:if test="count(//twc:command)=0">
                    <block>
                        <log cond="logDebug" expr="'No more commands.  Exiting.'" />
                        <exit />
                    </block>
                </xsl:if>
            </form>
        </vxml>
    </xsl:template>

    <xsl:template
        match="twc:command[@type='prompt' and contains(text(), 'TransferDialog')]">
        <transfer name="quicktransfer"  type="consultation">
            <xsl:attribute name="destexpr"><xsl:choose>
                <xsl:when test="//twc:parameter[twc:name='destination']">'<xsl:value-of
                select="//twc:parameter[twc:name='destination']/twc:value" />'</xsl:when>
                <xsl:otherwise>'tel:1136300'</xsl:otherwise>
            </xsl:choose>
            </xsl:attribute>
            <xsl:if test="//twc:parameter[twc:name='initial']">
                <prompt>
                    <xsl:call-template name="process_prompt">
                        <xsl:with-param name="prompt_type" select="'initial'" />
                    </xsl:call-template>
                </prompt>
            </xsl:if>
        </transfer>
    </xsl:template>

    <xsl:template
        match="twc:command[@type='prompt' and contains(text(), 'BasicDialog')]">
        <xsl:choose>
            <xsl:when test="//twc:parameter[twc:name='grammar']/twc:value">
                <field>
                    <xsl:attribute name="name"><xsl:value-of
                        select="//twc:parameter[twc:name='variable']/twc:value" /></xsl:attribute>
                    <noinput count="3">
                        <assign name="event" expr="'noinput'" />
                        <submit next="GetNextEvent2.jsp"
                            namelist="event lastResult lastResultMode lastResultValue srConfidence" />
                    </noinput>
                    <nomatch count="3">
                        <assign name="event" expr="'invalid'" />
                        <submit next="GetNextEvent2.jsp"
                            namelist="event lastResult lastResultMode lastResultValue srConfidence" />
                    </nomatch>

                    <xsl:for-each select="//twc:parameter[twc:name='grammar']/twc:value">
                        <grammar>
                            <xsl:attribute name="src"><xsl:if test="//twc:response/@base!=''"><xsl:value-of select="//twc:response/@base" /></xsl:if><xsl:value-of
                                select="." /></xsl:attribute>
                        </grammar>
                    </xsl:for-each>
                    <xsl:if test="//twc:parameter[twc:name='help']">
                        <help>
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'help'" />
                            </xsl:call-template>
                        </help>
                    </xsl:if>
                    <xsl:if test="//twc:parameter[twc:name='noinput1']">
                        <noinput count="1">
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'noinput1'" />
                            </xsl:call-template>
                        </noinput>
                    </xsl:if>
                    <xsl:if test="//twc:parameter[twc:name='noinput2']">
                        <noinput count="2">
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'noinput2'" />
                            </xsl:call-template>
                        </noinput>
                    </xsl:if>
                    <xsl:if test="//twc:parameter[twc:name='invalid1']">
                        <nomatch count="1">
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'invalid1'" />
                            </xsl:call-template>
                        </nomatch>
                    </xsl:if>
                    <xsl:if test="//twc:parameter[twc:name='invalid2']">
                        <nomatch count="2">
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'invalid2'" />
                            </xsl:call-template>
                        </nomatch>
                    </xsl:if>
                    <xsl:if test="//twc:parameter[twc:name='initial']">
                        <prompt>
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'initial'" />
                            </xsl:call-template>
                        </prompt>
                    </xsl:if>
                    <filled>
                        <log cond="logDebug" expr="'Filled.'" />
                        <assign name="event" expr="'OK'" />
                        <assign name="lastResult" expr="application.lastresult$.utterance" />
                        <assign name="lastResultMode" expr="application.lastresult$.inputmode" />
                        <assign name="lastResultValue" expr="application.lastresult$.interpretation" />
                        <assign name="srConfidence" expr="application.lastresult$.confidence " />
                        <submit next="GetNextEvent2.jsp"
                            namelist="event lastResult lastResultMode lastResultValue srConfidence" />
                    </filled>

                </field>
            </xsl:when>
            <xsl:when test="//twc:parameter[twc:name='initial']/twc:value">
                <block>
                    <xsl:if test="//twc:parameter[twc:name='initial']">
                        <prompt>
                            <xsl:call-template name="process_prompt">
                                <xsl:with-param name="prompt_type" select="'initial'" />
                            </xsl:call-template>
                        </prompt>
                    </xsl:if>
                    <submit next="GetNextEvent2.jsp"
                        namelist="event lastResult lastResultMode lastResultValue srConfidence" />
                </block>
            </xsl:when>
            <xsl:otherwise>
                <block>
                    <log cond="logDebug" expr="'Didn't find values for grammar or initial.  Exiting.'" />
                    <exit />
                </block>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="process_prompt">
        <xsl:param name="prompt_type" />
        <xsl:for-each select="//twc:parameter[twc:name=$prompt_type]/twc:value">
            <xsl:if test="contains(., '::')">
                <audio>
                    <xsl:for-each select="str:split(., '::')">
                        <xsl:if test="position()=1">
                            <xsl:attribute name="src"><xsl:if test="//twc:response/@base!=''"><xsl:value-of select="//twc:response/@base" /></xsl:if><xsl:value-of
                                select="." /></xsl:attribute>
                        </xsl:if>
                        <xsl:if test="position()=2">
                            <xsl:value-of select="." />
                        </xsl:if>
                    </xsl:for-each>
                </audio>
            </xsl:if>
            <xsl:if test="contains(., 'Date:')">
                <say-as interpret-as="date" format="ymd">
                    <xsl:for-each select="str:split(., ':')">
                        <xsl:if test="position()=2">
                            <xsl:value-of select="." />
                        </xsl:if>
                    </xsl:for-each>
                </say-as>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Вот некоторый XML:

<?xml version="1.0"?>
<response xmlns="http://twc.com/2009/01/ivr/framework" language="en-us" debug="true"
    base="/IVRFrameworkResources/Outage/">
    <command type="prompt"> BasicDialog <parameter>
            <name>initial</name>
            <value>en-us/prompts/OutageCleared.wav::Hello.  I'm letting you know the
                incident that caused your outage has been fixed. </value>
        </parameter>
    </command>
</response>
9
задан ericp 23 February 2010 в 11:23
поделиться

3 ответа

Трудно диагностировать проблемы с производительностью, не видя XSLT или не зная, насколько велики / сложны XML и XSLT.

Вы можете оплатить синтаксический анализ файла (ов), либо XSLT, либо XML, и / или у вас может быть очень неэффективная таблица стилей XSLT.

Например:

  1. Множество операторов // XPATH, которые, если они не нужны, могут снизить производительность для очень больших файлов XML.
  2. Логика скрыта внутри шаблонов , которые могут быть перемещены в критерии @match шаблона, что дает возможность для оптимизации механизмов XSLT.

Существуют профилировщики XSLT, которые можно использовать, чтобы увидеть узкие места в вашем XSLT. Например, oXygen имеет очень хороший отладчик / профилировщик : alt text alt text

Если вы будете запускать XSLT много раз, то вам следует ] кэшировать объект преобразователя . Таким образом, вы платите только за его однократную загрузку и создание и многократное использование.

Например, переместите экземпляр объекта XSLT Template в серверлет init ()

 TransformerFactory transFact = TransformerFactory.newInstance();
 Templates cachedXSLT = transFact.newTemplates(xsltSource);

, а затем, где вы выполняете преобразование, используйте кэшированный TransformerFactory obj:

Transformer t= cachedXSLT.newTransformer();
t.transform(xmlSource, result);
12
ответ дан 4 December 2019 в 13:01
поделиться

Я встречал какой-то инструмент, который преобразует XSLT файл в код парсинга java, но сейчас не могу найти ссылку. Извините за неполный ответ, но мне тоже интересно его найти.

-1
ответ дан 4 December 2019 в 13:01
поделиться

Даже при кешировании причина неприемлемой производительности часто кроется в самом коде XSLT , который вы вообще не показали.

По моему опыту, были случаи, когда мне удавалось изменить неэффективную реализацию XSLT таким образом, что она была ускорена в тысячи раз.

Довольно часто автор реализует алгоритм O (N ^ 2) или хуже, когда существует O (N) или даже O (log (N)) алгоритмов.

Укажите нам решаемую проблему и предоставьте код XSLT, который ее решает. Тогда кто-то может предложить вам более эффективное решение .

5
ответ дан 4 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: