2010-02-20 37 views
8

Tôi có một khung công tác tạo XML, dựa trên yêu cầu HTTP và trạng thái phiên hiện tại. Tôi có thể thử nghiệm trong HTML, nhưng sản lượng sản xuất sẽ là VXML - có lẽ một hoặc hai "hương vị" vì những lý do khác nhau.Tôi muốn cải thiện hiệu suất của xslt

Dưới đây là phần chậm chạp của HttpServlet của tôi:

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); 

hiện này có ~ 200ms. Tôi muốn nó nhanh hơn nhiều. Có lẽ < 10ms?

  1. Đề xuất lưu vào bộ nhớ cache? - thấy rằng các tệp xsl vẫn giữ nguyên trong suốt quá trình triển khai, các đối tượng Transformer có thể được lưu trữ vô thời hạn. Tôi đang nghĩ đến việc lưu vào bộ nhớ đệm trong cấp phiên, vì vậy mỗi phiên (1000 đồng thời) có riêng của họ. Bất kỳ đề xuất? Tôi có nên sử dụng bất kỳ khung công tác nào để lưu vào bộ nhớ đệm, vì bất kỳ lý do nào không?
  2. Có cách nào nhanh hơn để chuyển xml thành luồng phản hồi không?
  3. Tôi có nên xóa phần này và đi tuyến đường khác không? Nếu bạn nhận thấy sb.toString, tôi đang sử dụng một StringBuilder để lấy biểu diễn XML của các đối tượng (các đối tượng sử dụng một trình xây dựng chuỗi để tạo chuỗi XML). Mất khoảng 1 mili giây để tạo tài liệu XML bằng cách sử dụng StringBuilders, vì vậy tôi không quan tâm đến nó vào lúc này.

Edit:

Đây là tài liệu XSL. Tài liệu XML thường rất nhỏ. Chỉ cần một vài yếu tố. mẫu XML dưới 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> 

Dưới đây là một số 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

Bạn có thể hiển thị cho chúng tôi XSLT của bạn bằng tài liệu đầu vào mẫu không? Có thể XSLT của bạn chứa các truy vấn không hiệu quả có thể được tối ưu hóa (truy vấn không hiệu quả có thể được tạo trong hầu hết mọi ngôn ngữ truy vấn btw, vì vậy đổ lỗi cho XLST vì chậm thường không công bằng). –

+0

Tôi sẽ thêm XSLT, nhưng có lẽ đó có thể là một câu hỏi khác :) – ericp

+1

Bạn cũng có thể hiển thị tài liệu * đầu vào * không? Điều đó quan trọng hơn đầu ra. –

Trả lời

12

Rất khó để chẩn đoán các vấn đề hiệu suất mà không thấy XSLT hoặc biết XML/XSLT phức tạp và lớn đến mức nào.

Bạn có thể trả chi phí phân tích cú pháp (các) tệp, hoặc XSLT hoặc XML và/hoặc bạn có thể có biểu định kiểu XSLT rất kém hiệu quả.

Ví dụ:

  1. Rất nhiều // báo cáo XPATH, mà nếu không cần thiết có thể làm hại hiệu suất cho các tập tin XML rất lớn.
  2. Logic được chôn bên trong các mẫu có thể được chuyển lên tiêu chí mẫu @match, cung cấp cơ hội cho các công cụ XSLT tối ưu hóa.

Có các trình biên dịch XSLT mà bạn có thể sử dụng để xem các nút cổ chai trong XSLT của bạn ở đâu. Ví dụ, có một oXygen rất đẹp debugger/profiler: alt text alt text

Nếu bạn sẽ chạy XSLT nhiều lần, sau đó bạn nên cache the transformer object.Bằng cách đó, bạn chỉ phải trả chi phí để tải và khởi tạo nó một lần và tái sử dụng nhiều lần.

Ví dụ, di chuyển instantiation của đối tượng XSLT Template của bạn vào severlet bạn init()

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

và sau đó, nơi bạn thực hiện chuyển đổi, sử dụng cache TransformerFactory obj:

Transformer t= cachedXSLT.newTransformer(); 
t.transform(xmlSource, result); 
+3

+1 để sử dụng Mẫu. Nếu sử dụng Xalan làm máy biến áp XSLT, hãy thử sử dụng phiên bản XSLTC để biên dịch biểu định kiểu và nhanh hơn nhiều. Xem http://xml.apache.org/xalan-j/xsltc_usage.html#api Nếu sử dụng Xalan tôi muốn kiểm tra DOM được sử dụng, TinyTree có một số lợi thế chính so với Java DOM thông thường trong một số trường hợp (kết quả có thể thay đổi, nhưng việc sử dụng bộ nhớ tốt hơn cho TinyTree). –

-1

Tôi đã gặp một số công cụ có thể chuyển đổi tập tin XSLT vào mã phân tích cú pháp java, nhưng không thể tìm thấy bất kỳ tài liệu tham khảo ngay bây giờ. Xin lỗi vì câu trả lời chưa hoàn chỉnh, nhưng tôi cũng rất thú vị khi tìm thấy câu trả lời đó.

+0

Công cụ này là Saxon và Michael Kay vừa hỏi danh sách saxon-help nếu có ai cần nó, để anh ta biết liệu có tiếp tục duy trì nó hay không. Đăng trả lời của bạn ở đó. –

5

Ngay cả với bộ nhớ đệm, lý do cho hiệu suất không được chấp nhận thường trong mã XSLT chính nó - mà bạn chưa hiển thị.

Trong kinh nghiệm của tôi đã có những trường hợp khi tôi có thể thay đổi việc triển khai XSLT không hiệu quả theo cách mà nó đã được đẩy nhanh hàng nghìn lần.

Khá thường tác giả triển khai thuật toán O (N^2) hoặc tệ hơn, khi tồn tại thuật toán O (N) hoặc O (log) (N)).

Chỉ định cho chúng tôi vấn đề đang được giải quyết và cung cấp mã XSLT giải quyết nó. Sau đó, có thể ai đó sẽ cung cấp cho bạn giải pháp hoạt động tốt hơn.

Các vấn đề liên quan