codeflood logo

Sitecore 6.3 Performance

One of the things I remember being touted about Sitecore “Twin Peaks” which became Sitecore 6.3 was support for massive amounts of content. We’re talking thousands of child items in a single location. I’ve always worked to the rule of trying to keep the number of child items in any location to well under 100 items, and I don’t normally see more than about 30. John West recently also wrote some guidance about the number of child items one should aim for in the Information Architecture part of his Sitecore Best Practises series. This normally just means creating more folders to segment the content further. For example, if the site has a news section I wouldn’t just have the news items created under the news root item, but instead have an “item saving” event handler which moves the news item into an “archive” folder structure based on the year, month and day the news item is for. We wrote our own event handler here at Next Digital to handle this but John West has created the “News Mover” shared source module which does the same. Now aside from the performance implications of having a huge number of items in a single location there is also a usability issue. Requiring your authors to scroll through hundreds of items in the content tree is not good usability, even with different icons on the items (and in the case of news items all icons would be the same…). So regardless of whether Sitecore performs well or not with 1000 items, you should probably still try to limit the number of items anyway. But I was curious to see if Sitecore 6.3 really had delivered on this and so I did some performance testing between Sitecore 6.2 rev 100104 and Sitecore 6.3 rev 100716. For this performance test I used my good old trusty Revolver command prompt module which quickly lets me script out repetitive tasks. Unfortunately the current version of Revolver doesn’t contain a repetition command (well, it does against existing content through the find command); that’s flagged for Revolver 2. So to do what I wanted I just had to create 2 custom commands. The first of the commands I wanted just had to execute another command a specified number of times. Here’s the code for the Repeat command I created.

using System;
using Revolver.Core.Commands;
using Revolver.Core;
using System.Collections.Specialized;
using System.Text;

namespace sc63Perf
{
  public class Repeat : BaseCommand
  {
    public override string Description()
    {
      return "Repeat a command a number of times";
    }

    public override HelpDetails Help()
    {
      var details = new HelpDetails();
      details.Usage = "<cmd> count command";
      details.Description = Description();
      details.AddParameter("count", "The number of times to invoke the command");
      details.AddParameter("command", "The command to execute");
      details.AddExample("<cmd> 5 pwd");
      return details;
    }

    public override CommandResult Run(string[] args)
    {
      StringDictionary namedParameters = null;
      string[] numberedParameters = null;

      Util.ExtractParameters(out namedParameters, out numberedParameters, args);

      if (numberedParameters.Length < 1)
        return new CommandResult(CommandStatus.Failure, "Missing required parameter 'count'");

      if(numberedParameters.Length < 2)
        return new CommandResult(CommandStatus.Failure, "Missing required parameter 'command'");

      int count = 0;
      var parsed = int.TryParse(numberedParameters[0], out count);
      if(!parsed)
        return new CommandResult(CommandStatus.Failure, "Parameter 'count' is not a valid integer");

      string command = numberedParameters[1];
      var output = new StringBuilder();

      for (var i = 0; i < count; i++)
      {
        output.Append(Context.ExecuteCommand(command, FormatContext));
      }

      return new CommandResult(CommandStatus.Success, output.ToString());
    }
  }
}

I also need a way to create a unique name for each item I’m creating. Although I could try using the existing string manipulation commands I felt it would make more sense to simply create a command to increment an integer.

using System;
using Revolver.Core;
using Revolver.Core.Commands;

namespace sc63Perf
{
  public class Increment : BaseCommand
  {
    public override string Description()
    {
      return "Increment an integer";
    }

    public override HelpDetails Help()
    {
      var details = new HelpDetails();
      details.Description = Description();
      details.Usage = "<cmd> input";
      details.AddParameter("input", "An integer to process");
      details.AddExample("<cmd> 4");
      return details;
    }

    public override CommandResult Run(string[] args)
    {
      if (args.Length < 1)
        return new CommandResult(CommandStatus.Failure, "Missing required parameter 'input'");

      int num = -1;
      var parsed = int.TryParse(args[0], out num);

      if (parsed)
        return new CommandResult(CommandStatus.Success, (++num).ToString());
      else
        return new CommandResult(CommandStatus.Failure, "Parameter 'input' is not a valid integer");
    }
  }
}

I can use the touch command to create an item. I’ll base the name on an integer which I’ll increment for the next run. The repeat command above only accepts a single command to repeat, so I’ll have the create a Revolver script which will create the item and increment the name. Revolver scripts are stored in the core DB under the /sitecore/system/modules/revolver/scripts item. I’ll create a script called create with the following commands:

touch -t (sample/sample item) $a$
set a < (inc $a$)

The first line creates the item and uses the data in the environment variable a as the name. The next line increments the value in the environment variable a and stores it back. To get started I’ll need to bind my custom commands into my Revolver window.

bind sc63Perf.Repeat,sc63Perf rep
bind sc63Perf.Increment,sc63Perf inc

And before I start I’ll have to set the a environment variable to 1 so my first item will be named 1.

set a 1

The first test was for creating the items which I could run the other tests against. To create the items I can use the repeat command I bound to the moniker rep above.

timer (rep 50 create)

For each Sitecore version I created 50, 100, 200, 500, 1000 and 2000 items. Here’s the results. image As you can see Sitecore 6.3 shows good performance improvements on 6.2 at just over two thirds the time up the higher end. The next test was to query for a single item in those just created by ID.

timer (query *[@@id='{2729EE96-3F93-42C7-9AB2-81DB5FAC9A02}'] pwd)

image Sitecore 6.3 shows huge improvements on 6.2 at less than half the time for this query. The next test was to query for the same item by name

timer (query 500 pwd)

image Some quite odd artefacts at the lower end, but Sitecore 6.3 consistently performed better than 6.2, and if we consider the data point for 1000 items an outlier, all values for Sitecore 6.3 are less than 40% of the 6.2 value. This shows considerable improvement. The next test was to access each of the child items in turn.

timer (find pwd)

image At the top end Sitecore 6.3 performs at about 30% of the 6.2 values. The final test was to recycle the items.

timer (find rm)

image No huge performance improvements here. One notable artefact about this test was that for both Sitecore 6.2 and 6.3 I wasn’t able to get a reliable test value for 2000 items. But I was only really interested in comparison between the 2 versions, so no big deal. Well I think the data speaks for itself. Sitecore 6.3 shows considerable performance gains over Sitecore 6.2. But is it ready to support “massive” amounts of content? I’m not too sure if I can answer that being that ”massive” is such a subjective term. Even if it’s not, Sitecore are definitely headed in the right direction with these performance gains. And now that you get better performance with large volumes of content in a single location keep in mind that just because you can do something, doesn’t mean you should :)

Comments

KenB

This is great info. On the query by name test, did you repeatedly get the odd behavior of 1,000 items being so much slower than expected from the tests at 500 items and 2,000 items?
Would you be willing to run several rounds of Sitecore 6.3 tests between 500 and 1,000 to see where the performance drop-off becomes evident?
Also, do points at 1,250 and 1,500 fall linearly between the 1,000-2,000 results or do they drop back down from the oddness at 1,000?
Again, great work from you and the Sitecore coding team.

Great information here, but let me make one correction. Sitecore 6.3 is NOT the release that includes support for "massive amounts of content". And just to be clear, "massive" means millions of content items - the quantity of content that the largest websites require.
The main new features for 6.3 are support for clustered CM servers, the elimination of the staging module, support for SQL Server database replication and cloud-readiness.
The functionality added with Sitecore 6.3 provides the foundation for the "Massive" release, but Massive is a separate, future release. Per the product roadmap, this will be CMS 7.0.

Great article - nice to hear that they've squezed even more speed out of ye olde Sitecore engine:-)
I not sure you've got it right though, "twin peaks" i.e. 6.3 is support for multiple backend servers - hence all the cloud computing commotion going on from Sitecores side at the moment. The next major release of Sitecore - codenamed "massif" - is the release promising massive amounts of data in the database and in an unstructured manner. The concepts were introduced at the Dreamcore conference and means a complete rewrite of the underlying engine.

Leave a comment

All fields are required.