我有一个基于HTTP请求和当前会话状态生成XML的框架。我可以用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毫秒。我希望它更快。也许< 10ms的?
编辑:
这是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>
答案 0 :(得分:12)
如果不了解XSLT或了解XML和XSLT的大小/复杂程度,很难诊断性能问题。
您可能需要支付解析文件(XSLT或XML)的费用和/或您可能拥有效率非常低的XSLT样式表。
例如:
//
XPATH语句,如果不需要,会损害非常大的XML文件的性能。@match
条件中,这为XSLT引擎提供了优化的机会。您可以使用XSLT分析器来查看XSLT中的瓶颈所在。例如,oXygen有一个非常好的debugger/profiler:
如果您将多次运行XSLT,那么您应该cache the transformer object 。这样,您只需支付加载和实例化一次的成本并重复使用多次。
例如,将XSLT Template
对象的实例化移动到您的服务器小程序init()
TransformerFactory transFact = TransformerFactory.newInstance();
Templates cachedXSLT = transFact.newTemplates(xsltSource);
然后执行转换的位置,使用缓存的TransformerFactory
obj:
Transformer t= cachedXSLT.newTransformer();
t.transform(xmlSource, result);
答案 1 :(得分:5)
即使使用缓存,性能不可接受的原因通常在XSLT代码本身 - 您根本没有显示。
根据我的经验,有些情况下,我能够以这样的方式更改低效的XSLT实现,使其加速数千次。
作者经常使用O(N ^ 2)算法,或者更糟糕的是,当存在O(N)或甚至O(log(N))算法时。
向我们指定要解决的问题并提供解决它的XSLT代码。然后,某人可能会为您提供性能更佳的解决方案。
答案 2 :(得分:-1)
我遇到了一些将XSLT文件转换为java解析代码的工具,但现在找不到任何引用。很抱歉答案不全,但我也很有兴趣找到它。