6

I was wondering if there is any known difference (mostly performance related) between those two methods of retrieving all children of a given Item.

The first one will give me all levels of children in one shot.

On the second approach, I have to build some code to recursively get the same result, since Item.GetChildren() only returns the first level.

I don't know why but I had a feeling that the Item.Axes.GetDescendants() was always slower, but using DotPeek to see what is going on under the hoods now I'm no longer sure.

Item.Axes.GetDescendants()

It uses the item.Children property.

Which ends up calling ItemManager.GetChildren(this._ownerItem, (ChildListOptions.IgnoreSecurity & options) != ChildListOptions.None ? SecurityCheck.Disable : SecurityCheck.Enable).InnerChildren

Recursive Item.GetChildren()

Which is also ItemManager.GetChildren(this, (options & ChildListOptions.IgnoreSecurity) != ChildListOptions.None ? SecurityCheck.Disable : SecurityCheck.Enable, options)

7

I did some benchmarks using those two possibilities.

Scenario

Fetch 2040 items organized in the following way:

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

Using GetDescendants()

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

Using GetChildren() recursively

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

Results (in milliseconds)

After running both scenarios without any element cached at all (after restarting the IIS Pool on every run), those are the results I collected:

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

And those are the results when the tests were performed after all those elementes are cached properly:

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

So it looks like that even if the results are pretty close, using the method Item.GetChildren() recursively can be a little bit faster than the Item.Axes.GetDescendants().

3

Much faster way is to get descendants from index.

Query would be get all items that Path starts (contains) the same as current item + ID of item is different to current one.

Something like this:

var query = context.GetQueryable()
   .Where(item => item["_path"].Contains(contentRootId))
   .Where(item => !item.ID.Equals(contentRootId));

Solr can perform this in just few miliseconds.

  • If Solr document is enough. But how fast is it when you have to get the original item after? Maybe another series of tests? :) – Marek Musielak Jun 2 at 10:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.