Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Ferdy Hoefakker 214 posts 248 karma points
    Mar 06, 2013 @ 15:42
    Ferdy Hoefakker
    0

    XSLT performance bottleneck

    Hello,

    One of our sites is experiences performance issues. Using the umbDebugShowTrace I have narrowed it down to a specific XSLT file. Now, I have checked it over, and the only parts that (to me anyway) seem like they could be the cause are the for-each loops we use. I have however, no idea of how to get the data I need with another (more optimized) Xpath expression. If someone could take a look at this that'd be great.

    -Ferdy

    The xslt:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxml="urn:schemas-microsoft-com:xslt"
      xmlns:umbraco.library="urn:umbraco.library"
      exclude-result-prefixes="msxml umbraco.library">


    <xsl:output method="xml" omit-xml-declaration="yes" />

    <xsl:param name="currentPage"/>  
        
    <xsl:template match="/">
      <ul id="nav">
          
        <xsl:for-each select="$currentPage/ancestor-or-self::*[@isDoc]/descendant-or-self::*[@isDoc] [umbraco.library:HasAccess(@id,@path)  and string(naviHide) != '1' and (self::Nieuws or self::Pagina) and @level &gt; 0]">
          <xsl:sort select="@sortOrder" data-type="number" order="ascending" />
          <xsl:variable name="menuName" select="menuName"/>
          <li>
            <xsl:if test="contains(@nodeName, 'commerce')">
              <xsl:attribute name="class">menuHeaderCommerce</xsl:attribute>
            </xsl:if>
            <xsl:if test="contains(@nodeName, 'Meldpunt') or contains(@nodeName, 'point de')">
              <xsl:attribute name="class">menuHeaderMeldpunt</xsl:attribute>
            </xsl:if>
            <xsl:if test="contains(@nodeName, 'corporate')">
              <xsl:attribute name="class">menuHeaderCorporate</xsl:attribute>
            </xsl:if>
            <a href="{umbraco.library:NiceUrl(@id)}">
              <xsl:if test="contains(@nodeName, 'commerce')">
                <xsl:attribute name="class">menuHeaderCommerceA</xsl:attribute>
              </xsl:if>
              <xsl:if test="contains(@nodeName, 'corporate')">
                <xsl:attribute name="class">menuHeaderCorporateA</xsl:attribute>
              </xsl:if>
              <xsl:comment /><!--prevent self-close -->
              <span class="leftDiv"><!-- test -->&nbsp;</span>
              <span class="middleDiv">
                <!-- test -->
                <xsl:choose>
                  <xsl:when test="$menuName != ''">
                    <xsl:attribute name="title"><xsl:value-of select="$menuName"/></xsl:attribute>
                    <xsl:value-of select="$menuName"/><xsl:comment /><!-- Prevent self-closing element -->       
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:attribute name="title"><xsl:value-of select="@nodeName"/></xsl:attribute>
                    <xsl:value-of select="@nodeName"/><xsl:comment /><!-- Prevent self-closing element -->
                  </xsl:otherwise>
                </xsl:choose>
              </span>
              <span class="rightDiv"><!-- test -->&nbsp;</span>
            </a>        
             <xsl:call-template name="subItem" >
                <xsl:with-param name="parentPage"><xsl:value-of select="@id" /></xsl:with-param>
              </xsl:call-template>
          </li>
        </xsl:for-each>
        
      </ul>
    </xsl:template>        

    <xsl:template name="subItem">
    <xsl:param name="parentPage" />
    <xsl:variable name="parentLevel" select="umbraco.library:GetXmlNodeById($parentPage)/@level" />
    <xsl:comment><!-- --></xsl:comment>
    <xsl:if test="umbraco.library:GetXmlNodeById($parentPage)/@level > 1">
      <xsl:if test="count(umbraco.library:GetXmlNodeById($parentPage)/descendant::*[@isDoc and not (self::Website) and not(self::Event) and string(naviHide) != '1']) &gt; 0">
      <ul><xsl:comment />
        <xsl:for-each select="umbraco.library:GetXmlNodeById($parentPage)/descendant::*[@isDoc and not (self::Website) and (@level - $parentLevel = 1) and umbraco.library:HasAccess(@id,@path) and string(naviHide) != '1']">
          <xsl:sort select="@level"/>
          <xsl:sort select="@sortOrder" data-type="number" order="ascending" />
          <xsl:variable name="menuName" select="menuName"/>
          <li>
            <xsl:if test="$currentPage/@nodeName = @nodeName or ($currentPage/ancestor::*[@isDoc and not (self::Website)]/@nodeName = @nodeName)">
              <xsl:attribute name="class">active</xsl:attribute>
            </xsl:if>
            <a href="{umbraco.library:NiceUrl(@id)}"><xsl:comment /><!-- Prevent self-closing element -->
              <span class="leftDiv"><!-- test -->&nbsp;</span>
              <span class="middleDiv">
                <!-- test -->
                <xsl:choose>
                  <xsl:when test="$menuName != ''">
                    <xsl:attribute name="title"><xsl:value-of select="$menuName"/></xsl:attribute>
                    <xsl:value-of select="$menuName"/><xsl:comment /><!-- Prevent self-closing element -->       
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:attribute name="title"><xsl:value-of select="@nodeName"/></xsl:attribute>
                    <xsl:value-of select="@nodeName"/><xsl:comment /><!-- Prevent self-closing element -->
                  </xsl:otherwise>
                </xsl:choose>
              </span>
              <span class="rightDiv"><!-- test -->&nbsp;</span>
            </a>
          </li>
        </xsl:for-each>
      </ul>
      </xsl:if>
    </xsl:if>
    </xsl:template>

    </xsl:stylesheet>
  • Ferdy Hoefakker 214 posts 248 karma points
    Mar 07, 2013 @ 10:25
    Ferdy Hoefakker
    0

    Anyone?

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 11:32
    Alex Skrypnyk
    0

    Hi, Ferdy

    Why do you use 'descendant-or-self' and 'ancestor-or-self'? at one time?

     

    $currentPage/ancestor-or-self::*[@isDoc]/descendant-or-self::*[@isDoc]
     [umbraco.library:HasAccess(@id,@path)  and string(naviHide) != '1' and
    (self::Nieuws or self::Pagina) and @level &gt; 0]
  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 11:34
    Alex Skrypnyk
    0
    descendant-or-self 

    Grabs all children nodes. I think it's bottleneck

  • Ferdy Hoefakker 214 posts 248 karma points
    Mar 07, 2013 @ 11:59
    Ferdy Hoefakker
    0

    It's to build up the menu correctly. No matter the current page I am on, I ALWAYS want to start from the top. So, using ancestor-or-self I go to the root, and then grab everything below it.

    As I stated, I am pretty sure that is indeed the bottleneck. But I have no idea what would be a more efficient XPATH expression. Maybe I should add my node structure:

    root
    -website Dutch
    - - store news
    - - - categories
    - - - - news posts
    - - corporate news
    - - - categories
    - - - - news posts
    - - page with a form
    - - login page
    - - acces denied page
    -website Flemish
    - - store news
    - - - categories
    - - - - news posts
    - - corporate news
    - - - categories
    - - - - news posts
    - - page with a form
    - - login page
    - - acces denied page
    -website French
    - - store news
    - - - categories
    - - - - news posts
    - - corporate news
    - - - categories
    - - - - news posts
    - - page with a form
    - - login page
    - - acces denied page

    Whatever page I am on, I need to build a menu for the corresponding site (Dutch, Flemish or French). The menu items are the categories under the two news types (store and corporate). Not only that, but I need to start with a header for the store news, then display all it's categories. This is followed by a header for the corporate news which in turn has all its categories under it as menu items.

    I hope I explained this clearly enough.

    -Ferdy

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:20
    Alex Skrypnyk
    0

    Ferdy, could you give me link to your site ? ))

  • Ferdy Hoefakker 214 posts 248 karma points
    Mar 07, 2013 @ 12:22
    Ferdy Hoefakker
    0

    Afraid not, it's behind a login and contains sensitive information.

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:22
    Alex Skrypnyk
    0

    i think you shold remove this verification

    <xsl:iftest="count(umbraco.library:GetXmlNodeById($parentPage)/descendant::*[@isDoc
     and not (self::Website) and not(self::Event) and string(naviHide) !=
    '1']) &gt; 0"
    >

     

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:31
    Alex Skrypnyk
    100
    <xsl:for-eachselect="$currentPage/ancestor-or-self::*[@isDoc]/descendant-or-self::*[@isDoc]
     [umbraco.library:HasAccess(@id,@path)  and string(naviHide) != '1' and
    (self::Nieuws or self::Pagina) and @level &gt; 0]"
    >

    and this part should be like this:

    <xsl:for-eachselect="$currentPage/ancestor-or-self::*[@isDoc]/*[@isDoc]
     [umbraco.library:HasAccess(@id,@path)  and string(naviHide) != '1' and
    (self::Nieuws or self::Pagina) and @level &gt; 0]"
    >

    we don't need to grab all nodes each time, we have for-each in child template, there are we would only traverse on first level of pages


  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:33
    Alex Skrypnyk
    0

    you could build menu without any descendant axes

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:35
    Alex Skrypnyk
    0
    <xsl:with-paramname="parentPage"><xsl:value-ofselect="@id"/></xsl:with-param>

    why do you pass id into template ?

    passing all item is more optimal, and you don't need do this operation

    umbraco.library:GetXmlNodeById($parentPage)
  • Ferdy Hoefakker 214 posts 248 karma points
    Mar 07, 2013 @ 12:52
    Ferdy Hoefakker
    0

    Okay, removing the descendant-or-self on the first loop fixes it. It went from 5s on average to 0.5s difference between before- and after performing transformation.

    Your second suggestion is noted, but I think the above will already be more than enough. Not sure if I will be given the time to restructure the entire sub item template to accomodate such a change =\

    In any case, thanks!

    -Ferdy

  • Alex Skrypnyk 5908 posts 22603 karma points MVP 4x admin c-trib
    Mar 07, 2013 @ 12:55
    Alex Skrypnyk
    0

    It's my pleasure.

    We could cooperate) if you have a lot of umbraco projects )

    Alex )

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies