What is the fastest way of getting items? I present you the results of my experiment performed some time ago.
Introduction
Maybe the title is a little bit misleading because finding the fastest way of getting items was not my goal (you can find an answer for this too).
In the early days of Helix and Habitat, I was wondering if recommended approach for getting items with additional filtering is not a step back in terms of speed.
Previously I was using in my opinion the fastest way - queries
fast:/sitecore/content/*[@@templatename="TestItem"]
fast:/sitecore/content/*[@@templatename="TestItem"]
I was scared of:
item.Children.Where(i => TemplateManager.GetTemplate(i).InheritsFrom(id))
item.Children.Where(i => TemplateManager.GetTemplate(i).InheritsFrom(id))
I thought that it cannot be faster, but is what’s the truth?
Experiment
I decided to perform a test to find out what’s the truth.
Test Data
First I had to create some test data:
$root = "/sitecore/content" $testTemplate = New-Item -Path "/sitecore/templates/User Defined" -Name "TestItem" -ItemType "System/Templates/Template" [Sitecore.Data.Items.TemplateItem]$testTemplate = $testTemplate $performanceRoot = New-Item -Path $root -Name "PerformanceRoot" -ItemType $testTemplate.FullName 0..9 | % { $level0 = $_ $level0Parent = New-Item -Parent $performanceRoot -Name $level0 -ItemType $testTemplate.FullName 0..9 | % { $level1 = $_ $level1Parent = New-Item -Parent $level0Parent -Name $level1 -ItemType $testTemplate.FullName 0..9 | % { $level2 = $_ New-Item -Parent $level1Parent -Name $level2 -ItemType $testTemplate.FullName | Out-Null } } }
In content tree it looked like this:
Logic:
After I had my items ready in database I wrote different function for obtaining items. Note that that filtering in some methods is different than recommended by Helix (checking template name instead of inheritance)
public static Result GetDescendantsAllItems(Item item, ID id)
{
var r = new Result();
var items = item.Axes.GetDescendants()
.Where(i => TemplateManager.GetTemplate(i).InheritsFrom(id))
.ToList();
r.Items.AddRange(items);
return r;
}
public static Result ChildrenRecursive(Item item, ID id)
{
var r = new Result();
var itemChildren = item.Children;
var items = itemChildren
.Where(i => TemplateManager.GetTemplate(i).InheritsFrom(id))
.ToList();
r.Items.AddRange(items);
foreach (Item i in itemChildren)
{
if (i.HasChildren)
{
r.Items.AddRange(ChildrenRecursive(i, id).Items);
}
}
return r;
}
public static Result SelectItems(Item item, string query)
{
var r = new Result();
r.Items.AddRange(item.Axes.SelectItems(query));
return r;
}
public static Result ChildrenSingleLevel(Item item, ID id)
{
var r = new Result();
var items = item.Children
.Where(i => TemplateManager.GetTemplate(i).InheritsFrom(id))
.ToList();
r.Items.AddRange(items);
return r;
}
Note: "SelectSingleItem(query)" it will always works with string type query param
public static Result SelectItem(Item item, string query)
{
var r = new Result();
r.Items.Add(item?.Axes.SelectSingleItem(query));
return r;
}
public static Result GetDescendantsSingleItem(Item item, ID id)
{
var r = new Result();
var items = item.Axes.GetDescendants()
.FirstOrDefault(i => TemplateManager.GetTemplate(i).InheritsFrom(id));
r.Items.Add(items);
return r;
}
public static Result ChildrenSingleItem(Item item, ID id)
{
var r = new Result();
var items = item.Children
.FirstOrDefault(i => TemplateManager.GetTemplate(i).InheritsFrom(id));
r.Items.Add(items);
return r;
}
public static Result SelectItemFast(Item item, string query)
{
var r = new Result();
r.Items.Add(item.Database.SelectSingleItem(query));
return r;
}
public static Result SelectItemsFast(Item item, string query)
{
var r = new Result();
r.Items.AddRange(item.Database.SelectItems(query));
return r;
}
Tests:
After everything was setup I performed tests. I used something like this:
$item = Get-Item .
$templateItem = Get-Item -Path "/sitecore/templates/User Defined/TestItem"
Write-Host "`nGetDescendants - AllItems" -ForegroundColor Green
$GetDescendantsAllItems = [Tests]::GetDescendantsAllItems($item, $templateItem.ID)
$GetDescendantsAllItems.Items.Count
$GetDescendantsAllItems.TimeSpan.TotalMilliseconds
Write-Host "`nChildren - Recursive" -ForegroundColor Green
$ChildrenRecursive = [Tests]::ChildrenRecursive($item, $templateItem.ID)
$ChildrenRecursive.Items.Count
$ChildrenRecursive.TimeSpan.TotalMilliseconds
Write-Host "`nSelect Items - AllItems" -ForegroundColor Green
$SelectItemsRecursive = [Tests]::SelectItems($item, ".//*[@@templatename='TestItem']")
$SelectItemsRecursive.Items.Count
$SelectItemsRecursive.TimeSpan.TotalMilliseconds
Write-Host "`nSelect Items Fast - AllItems" -ForegroundColor Green
$query = "fast:$($item.Paths.path)//*[@@templatename='TestItem']"
$SelectItemsFast = [Tests]::SelectItemsFast($item, $query, $count)
$SelectItemsFast.Items.Count
$SelectItemsFast.TimeSpan.TotalMilliseconds
Write-Host "`nChildren - SingleLevel" -ForegroundColor Green
$ChildrenSingleLevel = [Tests]::ChildrenSingleLevel($item, $templateItem.ID)
$ChildrenSingleLevel.Items.Count
$ChildrenSingleLevel.TimeSpan.TotalMilliseconds
Write-Host "`nSelect Items - SingleLevel" -ForegroundColor Green
$SelectItems = [Tests]::SelectItems($item, "./*[@@templatename='TestItem']")
$SelectItems.Items.Count
$SelectItems.TimeSpan.TotalMilliseconds
Write-Host "`nGetDescendants - SingleItem" -ForegroundColor Green
$GetDescendantsSingleItem = [Tests]::GetDescendantsSingleItem($item, $templateItem.ID)
$GetDescendantsSingleItem.Items.Count
$GetDescendantsSingleItem.TimeSpan.TotalMilliseconds
Write-Host "`nChildren - SingleItem" -ForegroundColor Green
$ChildrenSingleItem = [Tests]::ChildrenSingleItem($item, $templateItem.ID)
$ChildrenSingleItem.Items.Count
$ChildrenSingleItem.TimeSpan.TotalMilliseconds
Write-Host "`nSingle Item - SingleLevel" -ForegroundColor Green
$SelectItem = [Tests]::SelectItem($item, "./*[@@templatename='TestItem']")
$SelectItem.Items.Count
$SelectItem.TimeSpan.TotalMilliseconds
Write-Host "`nSingle Item - Recursive" -ForegroundColor Green
$SelectItemRecursive = [Tests]::SelectItem($item, ".//*[@@templatename='TestItem']")
$SelectItemRecursive.Items.Count
$SelectItemRecursive.TimeSpan.TotalMilliseconds
Write-Host "`nSelect Item Fast - SingleItem" -ForegroundColor Green
$query = "fast:$($item.Paths.path)/*[@@templatename='TestItem']"
$SelectItemFast = [Tests]::SelectItemFast($item, $query, $count)
$SelectItemFast.Items.Count
$SelectItemFast.TimeSpan.TotalMilliseconds
Write-Host "`nSelect Item Fast - AllItems" -ForegroundColor Green
$query = "fast:$($item.Paths.path)//*[@@templatename='TestItem']"
$SelectItemFast = [Tests]::SelectItemFast($item, $query, $count)
$SelectItemFast.Items.Count
$SelectItemFast.TimeSpan.TotalMilliseconds
If you are going to try it by yourself ::
Don’t forget to update the max number of items in a query result set (Query.MaxItems
)
Note: How we can call c# code Action method from poershell script.
Comments
Post a Comment