[USPC] Ultimate Sitecore Performance Championship: GetChildren() vs Axes.GetDescendants()

I’m that kind of guy who is always asking himself if this given method has a better performance than that other one, even if I know that it doesn’t make any real difference in 97.4% of the cases. It’s almost like a national sport on Santos’s house.

I was surprised and shocked when I realized that there aren’t a lot of articles/posts on the Sitecore blogosphere about performances battles. That’s why I decided it was time to convert those personal benchmarks into useful public material.

Ladies and gentlemen, that’s how the USPC was born.

giphy

USPC – Fight 1

And nothing better to start this blog series than the most simple methods battle possible. The one that every single Sitecore developer will use multiple times in their careers. Yes, ladies and gentlemen, I’m talking about getting the current Item children. For the records, I used a Sitecore 8.2 as an arena.

On The Red Corner… Item.GetChildren()

This is possibly the very first method every one of us learned when having the first contact with Sitecore. It’s without a doubt the most simple way of navigating through item’s children because it’s totally intuitive. You get the item’s instance, type .get and let the autocomplete do its magic. The .GetChildren() will be there, just waiting to be used.

giphy-1

On The Blue Corner… Item.Axes.GetDescendants()

This second option is for sure less known, but if your goal is to get all the children including multiple levels of navigation, it only takes one line of code. Anyway, it uses two dots so it must be more complicated, right? That’s what we will see.

giphy-2

Are You Ready? Let’s Get It On!

So in order to be able to benchmark those big boys, we need to define a fair scenario. In today’s fight, it’s going to be “What is the fastest way of getting all the children from a given item, including multiple levels descendants?”.

More precisely, fetch 2020 descendants items organized in the following way:

Root Item
    - SubItems 1
        - SubItems 1.1        
        (100 items)     
    (100 items)
    - SubItems 2.1
        - SubItems 2.1        
        (100 items) 
    (100 items) 
    [...]
    - Bulk Items 10
        - Bulk Items 10.1       
        (100 items)     
    (100 items)

Each fighter will be executed multiple times and the average execution time will be used to determine the winner tonight.

The GetChildren() Fight Strategy

Since this method won’t fetch all levels of descendants by default, we need to define a strategy to do so, otherwise, it would be an easy victory to GetDescendants().

Let’s use simple tail recursion.

IEnumerable<Item> kids = FetchAllChildrenItems(Database.GetItem(rootItemId)).ToList();

private IEnumerable<Item> FetchAllChildrenItems(Item p_Item, bool p_ReturnRootItem = false)
{
    if (p_ReturnRootItem) {
        yield return p_Item;
    }

    foreach (Item child in p_Item.GetChildren(ChildListOptions.SkipSorting))
    {
        foreach (Item subChild in FetchAllChildrenItems(child, true)) {
            yield return subChild;
        }
    }
}

The GetDescendants() Fight Strategy

Not a big deal for him, this method already pulls all children from all levels by default. It will play it safe and do nothing else.

IEnumerable<Item> kids = Database.GetItem(rootItemId).Axes.GetDescendants().ToList();

The Judges Final Decision

The first execution batch was pretty simple. All the 2020 items were cached and the code was called as part of the HttpRequestBegin pipeline. And those are the final results in milliseconds:

1. GetDescendants():
    34.0887
    27.0741
    18.0443
    21.054
    24.0315
    29.0764
    Average: 25.5615
 2. GetChildren() - Recursive:
    15.0413
    19.0475
    20.0525
    17.0444
    16.0744
    24.0643
    Average: 18.5540

Easy victory to GetChildren()!

giphy-4

But what about running those on a fresh Sitecore instance with no cache at all? I executed an iisreset before each running and those were the results:

1. GetDescendants():
    4529.0435
    2880.6591
    3169.9953
    2709.0039
    Average: 3322.1754
 2. Children - Recursive:
    2305.6319
    2470.5706
    2372.3421
    2581.8652
    Average: 2432.6024

Again, victory to the contender on the red corner.

giphy-5

Conclusion

It was pretty close, but the Item.GetChildren() may be faster

It’s all because it is more flexible. You can, for instance, pass the ChildListOptions.SkipSorting option which is responsible for a huge performance gain.

giphy-3

That means that depending on your requisites (when sorting matters), it may be better to just go ahead and use the one-liner solution. Less code is usually better.

Please note that the project with the complete solution is on my GitHub as a public repository. Fell free to play with it if you want.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s