Custom Item Display Performance

Topics: Customizing Orchard, Writing modules
Jul 13, 2015 at 5:11 PM
Edited Jul 13, 2015 at 5:12 PM
I've written a module to search in custom content items and display a paged list of results.
This all works fine until you press Show All and there is >70 items in the list.
The page waits for 10-20s before loading.
When debugging everything stops responding when it hits
  list.AddRange(results.Skip(pager.GetStartIndex())
                        .Select(r => _contentManager.BuildDisplay(r, "Summary")));
Changing the view to static text rather dynamic based on content made little difference.

What could BuildDisplay be doing that cause such a slow down when displaying a lot of items?
Jan 30 at 4:57 AM
Hey,

Did you ever solve this? I'm having the exact same problem.

Kr,

Borrie
Feb 4 at 11:10 AM
Edited Feb 4 at 11:10 AM
Hi Borrie,

I did a couple of things to help.
The big issues was in our custom driver, it was returning a combined option of 4 Shapes
public class MyItemDriver : ContentPartDriver<MyItemPart>

 protected override DriverResult Display(MyItemPartpart, string displayType, dynamic shapeHelper)
{
   . . .
 return Combined(
                ContentShape("Parts_MyItem",
                () => shapeHelper.Parts_MyItem(
                    ContentPart: part,
                    ContentItem: part.ContentItem,
                   . . .
                  )),
                ContentShape("Parts_MyItem_Summary",
                    () => shapeHelper.Parts_MyItem_Summary(
                    ContentPart: part,
                    ContentItem: part.ContentItem,
                    . . .
                   )),
                ContentShape("Parts_MyItem_SummaryMap",
                    () => shapeHelper.Parts_MyItem_SummaryMap(
                    ContentPart: part,
                    ContentItem: part.ContentItem,
                   . . .
                    )),
                ContentShape("Parts_MyItem_SummaryAdmin",
                    () => shapeHelper.Parts_MyItem_SummaryAdmin(
                    ContentPart: part,
                    ContentItem: part.ContentItem,
                   . . .
                   ))
                );
}
This was changed to a case statement to use the displayType parameter and the content returned was reduced to fit what was needed for the view.
 protected override DriverResult Display(PropertyInfoPart part, string displayType, dynamic shapeHelper)
        {
           . . .       
            switch (displayType)
            {  
              case "Summary":
                    return ContentShape("Parts_MyItem_Summary", 
                   . . .
                     break;
                case "SummaryMap":
                    return ContentShape("Parts_MyItem_SummaryMap", 
                   . . . 
                   break;
               case "SummaryAdmin":
                    return ContentShape("Parts_MyItem_SummaryAdmin", 
                   . . .
                    break;
                default:
                     return ContentShape("Parts_MyItem",
                   . . .
For our content it is imported daily so I also added in a cache in the controller
So instead of
                    list.AddRange(results.Skip(pager.GetStartIndex())
                        .Take(pager.PageSize)
                        .Select(r => _contentManager.BuildDisplay(r, "Summary")));
It checks the cache for a current version or updates the cache and returns the display
 ObjectCache cache = MemoryCache.Default;
. . .
  list.AddRange(results.Skip(pager.GetStartIndex())
                        .Take(pager.PageSize)
                        .Select(r =>
                            checkCache(cache, r, "Summary")));
. . .
 private object checkCache(ObjectCache cache, ContentItem r,String displayType)
        {
            if (!cache.Contains(r.Id.ToString() + "_" + displayType))
            {
                CacheItemPolicy policy = new CacheItemPolicy();
                policy.AbsoluteExpiration = DateTimeOffset.Now.AddDays(1);
                cache.Set(r.Id.ToString() + "_" + displayType, _contentManager.BuildDisplay(r, displayType), policy);
            }
            return cache[r.Id.ToString() + "_" + displayType];
        }
The scheduled importer invalidates the cache for any changed content.
Feb 5 at 12:26 PM
Dear,

Thank you so much for your answer!

I don't think i completely understand, i'm using all the standard build in features, I need info like standard title, added fields and termparts.

How would i rewrite the standard _contentManager.BuildDisplay to strip this down?

Kr,

Borrie
Nov 25 at 2:55 PM
ar_escrivo,

I've finally implimented your code :) It works but the weird thing is the cashed items or displayed as a html list not as the other shapes.. Need to solve that

My real question now, is there a way to have a sort of script that cashes these every night? this would make my site a lot faster in stead of cashing them by usage

Borrie