У меня есть платформа, которая генерирует 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 мс?
Править:
Вот документ 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>
Трудно диагностировать проблемы с производительностью, не видя XSLT или не зная, насколько велики / сложны XML и XSLT.
Вы можете оплатить синтаксический анализ файла (ов), либо XSLT, либо XML, и / или у вас может быть очень неэффективная таблица стилей XSLT.
Например:
//
XPATH, которые, если они не нужны, могут снизить производительность для очень больших файлов XML. @match
шаблона, что дает возможность для оптимизации механизмов XSLT. Существуют профилировщики XSLT, которые можно использовать, чтобы увидеть узкие места в вашем XSLT. Например, oXygen имеет очень хороший отладчик / профилировщик :
Если вы будете запускать XSLT много раз, то вам следует ] кэшировать объект преобразователя . Таким образом, вы платите только за его однократную загрузку и создание и многократное использование.
Например, переместите экземпляр объекта XSLT Template
в серверлет init ()
TransformerFactory transFact = TransformerFactory.newInstance();
Templates cachedXSLT = transFact.newTemplates(xsltSource);
, а затем, где вы выполняете преобразование, используйте кэшированный TransformerFactory
obj:
Transformer t= cachedXSLT.newTransformer();
t.transform(xmlSource, result);
Я встречал какой-то инструмент, который преобразует XSLT файл в код парсинга java, но сейчас не могу найти ссылку. Извините за неполный ответ, но мне тоже интересно его найти.
Даже при кешировании причина неприемлемой производительности часто кроется в самом коде XSLT , который вы вообще не показали.
По моему опыту, были случаи, когда мне удавалось изменить неэффективную реализацию XSLT таким образом, что она была ускорена в тысячи раз.
Довольно часто автор реализует алгоритм O (N ^ 2) или хуже, когда существует O (N) или даже O (log (N)) алгоритмов.
Укажите нам решаемую проблему и предоставьте код XSLT, который ее решает. Тогда кто-то может предложить вам более эффективное решение .