Cascade Server’s Index Blocks vs Locator Tool vs Query API

I’ve compared performance using Cascade Server’s Index Blocks, Velocity Locator Tool and the new (as of version 7.12.2) Query API.

The method:

I setup 3 configurations in a configuration set to get a little over 800 assets.

  1. use an index block that includes metadata and XML inline (i.e. structured data)
  2. use velocity’s locator tool to loop through folders and get children down 3 levels.
  3. use velocity’s Query API to get pages of a specific content type (no limit)

The implementation:

Index block without XML inline:

Screen Shot 2014-09-23 at 10.00.11 AM

with XML inline:

Screen Shot 2014-09-23 at 10.00.32 AM

Velocity Locator Tool:

#set($articlesFolder = $_.locatePage($currentPagePath, $currentPageSiteName).parentFolder)
#set($years = $articlesFolder.children)

#foreach($year in $years) 
  #if($year.identifier.type == "folder")
    #foreach($month in $year.children)
      #foreach ( $article in $month.children )
          #set ( $title = $article.metadata.title.replaceAll("&","&").replaceAll("&","&") )
          #set ( $link = $article.path )
          #set ( $startDate = $article.metadata.startDate)
          #set ( $category = $article.metadata.getDynamicField("category").value )
          #set ( $categoryStripped = $category.replaceAll("-", " ") )
          <li class="article $category">
            <span class="date $category">$_DateTool.format('MMMM d, yyyy', $startDate)</span> <a href="$link" class="title">$title</a>
            <div class="category $category">$categoryStripped</div>
        #end ## start date
      #end ## articles
    #end ## month
  #end ## type
#end ## year

Velocity Query API:

#set($articles = $_.query().byContentType('article').maxResults(9999).sortBy('startDate').sortDirection('desc').indexableOnly(true).publishableOnly(true).execute())
#foreach ( $article in $articles )
    #set ( $title = $article.metadata.title.replaceAll("&amp;","&").replaceAll("&","&amp;") )
    #set ( $link = $article.path )
    #set ( $startDate = $article.metadata.startDate)
    #set ( $category = $article.metadata.getDynamicField("category").value )
    #set ( $categoryStripped = $category.replaceAll("-", " ") )
    <li class="article $category">
      <span class="date $category">$_DateTool.format('MMMM d, yyyy', $startDate)</span> <a href="$link" class="title">$title</a>
      <div class="category $category">$categoryStripped</div>
  #end ## start date
#end ## article

The results:

Index blocks were fast if only indexing metadata and not including XML inline (i.e. the structured data)Screen Shot 2014-09-22 at 4.20.54 PM:

but as soon as you need any of the data from the structured data it slows down significantly:

Screen Shot 2014-09-22 at 4.16.52 PM



The Locator Tool was just slow, which makes sense, because it’s a nested loop getting objects for each iteration. That’s a lot of interactions with the system.

Screen Shot 2014-09-22 at 4.17.42 PM



The Query API is also fairly slow when dealing with large sets of data… keep in mind the objects returned with the Locator Tool and the Query API include metadata AND structured data.

Screen Shot 2014-09-22 at 4.18.10 PM

What we can learn from the tests

If you’re only using the metadata from assets then definitely go with Index Blocks

If you’re also using structured data from assets then you’ll likely need to use the Locator Tool and/or the Query API. Index blocks take much longer to render and usually have a limit to number of pages to index. The Query API does allow for sorting and filtering by metadata and content type which could be considerably faster than using the Locator Tool to filter through objects.

Note: here is Hannon Hill’s official statement on Velocity Locator Tool and Performance

Locator Tool can be considered an alternative to Index Blocks altogether. Most formats that use Index Blocks could be rewritten to use Locator Tool instead. Using the Locator Tool in general is much slower than retrieving assets with an Index Block, in that for example, an Index Block with 1,000 assets rendered will generally complete rendering much faster than if a Locator Tool was to perform locate() calls 1,000 times, especially if Index Block rendering cache is used. However, in most cases, the reason for rendering so many assets in an Index Block is only so that it encompasses just a few assets that are really needed for the rendering of a specific Page, such assets being usually spread out across the system. In these scenarios, using the Locator Tool just a few times versus rendering an Index Block with 1,000 assets in it is going to be much faster and a better solution.

To prevent the possibility of a Velocity Format from rendering too slowly or taking too many system resources, and therefore to prevent the Velocity Formats from potentially making the system unstable, the maximum Format transformation time has been set to 5 minutes. After that time, the rendering process will stop, also preventing the Page from getting published. To prevent this from happening, developers should be careful of the number of times the Locator Tool is being used as well as number of times referencing properties are being accessed (examples: asset’s parent Folder, Folder’s children, an asset selected through structured data asset chooser).

Searching entire Dreamweaver site for files by content

I often want to search my entire site for files that contain a specific word, phrase or string. The best way to do this, that I found, was to GET the entire Dreamweaver site to your computer so now you have all the files locally. Then you can use Dreamweaver search (CTRL + F) to search the entire local site for content. Hope this helps and if not here are some additional sources:

jQuery JSONP Cross-domain AJAX Callback Function

There may be times where you need to make an AJAX call to a resource from another domain, but browsers will not allow a simple AJAX GET. Instead you’ll need to implement a callback function and use JSONP. Here’s an example of the requesting AJAX script:

var username = 'liljosh';
var url = '//'+username+'&output=json&callback=?';
        $.getJSON(url, function (data) {

and the callbackScript.php could look like this:

output("Username is $_GET[username]");

// output as JSON
function output($html) {
    if(isset($_GET['callback'])) $html = $_GET['callback'] . '(' . json_encode($html) . ')';