ASPX templates
Version 4.x > ASPX templates > Caching and personalization View modes: 
User avatar
Member
Member
Steve-Appetere - 7/29/2009 9:09:26 AM
   
Caching and personalization
Hi

The Developer's Guide section, Caching & Performance -> Caching Options -> Caching and personalization, explains that each item in the cache includes the current user name as part of the CacheItemName.

So, as the guide says, if you have a large number of simultaneous logged-in users, you can't really use caching as this would use a lot of memory. The implication being that sites with lots of members may have worse performance than one that is only for the public, where caching can be used.

I have a couple of questions about this, if anyone can help please?

1. Making WebPart caching non-specific to the user

Is there a way to globally change the CacheItemName of WebParts, so that it is just based on site name, page path, web part ID without the current user name?

My thinking here is that this would at least mean content which is identical to all users could be cached only once.

(Perhaps I could subclass CMSAbstractWebPart & override the CacheItemName property, then have any WebParts inherit from the modified version?

Or would I need to manually set the property in code for each WebPart that is used?)

Would there be any unexpected consequences of doing this?

2. Security settings

If the WebPart CacheItemName was changed, as in the previous question, how will security be applied?

For example:

- Will page-level security still work (seems that it should)

- If "CheckPermissions" is set on a WebPart, but the user name is not part of CacheItemName, will permissions still be checked before the cached content is used? Or will the second person to request the WebPart contents just get whatever the previous person's permissions entitled them to see (because the permission checks are not carried out again)?

I hope I am asking sensible questions here. But in summary, what I really trying to understand is how best to set up caching for a site with lots of logged-in members.

Thanks,

Steve

User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 8/3/2009 8:27:42 AM
   
RE:Caching and personalization
Hello,

1. You can suit it if you have the same content for all users.
Regards the global approach:
You may change it in the full source code (if you have it) or override the CMSAbstractWebPart class and use this new suited class for web parts you need.

2. The cache stores the content with applied security restrictions. If you change the behavior (so that it does not identify the user) it will cache the first user and displays the same content to all others. The security settings are checked before saving to cache. If you get the content of cache the permissions are not controlled again.

Best regards,
Helena Grulichova

User avatar
Member
Member
Steve-Appetere - 8/5/2009 10:26:45 AM
   
RE:Caching and personalization
Thanks Helena. I'll look into making some changes myself.

But if I have understood this correctly, then the performance of any site that uses membership (eg social networking, ecommerce) is effectively going to be as if there were no caching?

My reasoning is that the username is always part of the cache's key for the three types of Kentico caching:

- images
- WebPart content
- full-page

So each user will have their own cache (if you have enough memory to enable caching at all), and will not benefit from the cache already being populated by someone else.

So I'd guess this will make Kentico sites with many logged-in users really rather slow?

This probably should go in the enhancement requests forum, but would the system not perform better with a similar approach to caching offered by ASP.NET datasources? Here the cache is populated by effectively using the SQL statement as the key. So if two users, logged in or not, request exactly the same data, then the database query is avoided.

The page still has to be built, but the most time-consuming database operations can largely be replaced by cache fulfilment.

Just a thought..

Regards

Steve

User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 8/6/2009 5:35:33 AM
   
RE:Caching and personalization
Hi Steve,

our cache system stores the results of application process not the raw results of SQL queries. The content (of web parts) has the possibility to set up the cache item name so that it would store the same content for more than 1 user. But we admit the system could be more effective for sites with many users. We will review and improve the system in one of next versions. Thank you for your suggestions.

Best regards,
Helena Grulichova

User avatar
Member
Member
Steve-Appetere - 8/6/2009 9:07:56 AM
   
RE:Caching and personalization
Hi Helena

I have taken the approach of manually setting the CacheItemName for each WebPart that I want a single entry in the cache for (regardless of who is logged in) - using a key like "SiteName_PageAlias_ControlID". This is actually pretty quick to do & maintain, so I am less concerned now about the performance of the site.

A couple of other thoughts about caching for you, maybe for future versions:

One Kentico behaviour I noticed, is that if you have

CMS Site Manager -> Settings -> Web site -> Cache content (minutes) = 0

then WebPart caching is completely turned off, meaning you cannot override the CacheItemKey & CacheMinutes property on an individual WebPart, and have this cached on its own.

Would it not be more flexible to enable content caching on any WebPart that requests it by setting a CacheMinutes value?

Also for Full Page Caching, it would be ideal if you could also specify a CacheItemName for each page too. This would be great for my Home Page, where I could cache a single copy for all browsers & users, making the performance on that page much better.

Regards

Steve

User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 8/7/2009 2:38:26 AM
   
RE:Caching and personalization
Hi Steve,

The individual settings of web parts should be stronger than global configuration, I have discuss it with our developers. Could you please tell me how you found out it?

The cache name for pages will be considered. Thank you.

Best regards,
Helena Grulichova

User avatar
Member
Member
Steve-Appetere - 8/7/2009 4:05:33 AM
   
RE:Caching and personalization
When I tried to reproduce this, I found that you are right that the WebSite setting does successfully override the Global settings for caching (even if the time is set to zero).

The problem was actually due to how I specified the settings. For example, if you set the properties in the WebPart (in my ASPX template page), the caching works fine:


<uc1:repeater runat="server" ID="newsRepeater"
CacheItemName="MySite_Home_newsRepeater_Hardcoded"
CacheMinutes="10"

ClassNames="CMS.News"
EnableViewState="False"
OrderBy="NewsReleaseDate DESC"
Path="/news/%"
SelectTopN="4" TransformationName="CMS.News.NewsWithSummaryAndTeasers" />


But, if you set the same properties in the code-behind page, in an overriden OnInit method, the WebPart does not use the properties you specify.

When I was testing, I think I changed the CacheMinutes in code, but set the CacheItemName in the markup, hence giving the symptoms I descirbed.

Zdenek Cetkovsky is looking into this for me, via a direct support email I sent, and thinks the reason the code-set properties are not being used it is probably due to lifecycle differences of some sort.

Regards

Steve

User avatar
Member
Member
Steve-Appetere - 8/7/2009 8:05:26 AM
   
RE:Caching and personalization
I've had a reply from Zdenek, copied below, and now I can get the WebPart caching to behave how I would like.

Even in OnInit() it is not enough early to set the caching properties.

In the aspx page in CMSRepeater definition (let's say of ID="repeatersID" for illustration), please add a property

StopProcessing="True"

and then it OnInit (although it could be used also somewhat later) in code behind please use:

repeatersID.StopProcessing="False";
repeatersID.ReloadData(true);



Thanks to you both for the help,

Steve

User avatar
Member
Member
dmco - 4/3/2010 11:09:54 PM
   
RE:Caching and personalization
Hi Steve

I'm hoping you can help me getting the CacheItemName set for my CMSListMenu.
As you said earlier in this thread, the cache item name doesn't seem to be set if you put it in the codebehind.

I've tried the StopProcessing/ReloadData workaround you posted above, but still no joy.

If you have a moment, would you mind taking a glance over what I've done (below) and see if there's anything I'm forgetting or misunderstanding?


I have a CMSListMenu (ID="LeftTreeMenu") in my master page (Administration.master)
I would like this menu to be cached by role/page, on the understanding that that would mean only one cached copy would be stored of the menu content for each role for each page.

My menu is declared as follows

<uc1:cmslistmenu runat="server" ID="LeftTreeMenu" Path="/{0}/%" SelectOnlyPublished="true"
HighlightAllItemsInPath="true" MaxRelativeLevel="3" EnableViewState="false" CheckPermissions="true"
DisplayHighlightedItemAsLink="true" CacheMinutes="20" StopProcessing="true" />

In the Init() method of the Administration.master page, I have the following:


LeftTreeMenu.CacheItemName = GetCacheItemName(); //<== returns <site>_<page>_<controlID>_<role>
LeftTreeMenu.StopProcessing = false;
LeftTreeMenu.ReloadData();

object output;
LogManager logManager = new LogManager();
if (!CacheHelper.TryGetItem(LeftTreeMenu.CacheItemName, out output))
{

logManager.LogInfo("Menu for string {0} was not in cache", LeftTreeMenu.CacheItemName);
}
else
{
logManager.LogInfo("Menu for string {0} was in cache", LeftTreeMenu.CacheItemName);
}



That all looks sweet to me, but refreshing the page multiple times, the string is never found in the cache.
If I put some value in the ASPX, the key IS found in the cache.

Any idea what the problem might be?

Thanks very much


User avatar
Kentico Developer
Kentico Developer
kentico_helenag - 4/13/2010 3:39:08 AM
   
RE:Caching and personalization
Hi,


The code seems to be OK for me.

Could you please move the condition: if (!CacheHelper.TryGetItem ... to some rather late method? Maybe only the condition fails in that moment.


Best regards,
Helena Grulichova