There are few things more rewarding in site performance than enabling the Output Cache. This will store the ready-generated HTML to be served without executing any WebForms pages or Controller actions and their respective Views for MVC sites.
In Episerver, the output cache is enabled in the applicationSettings element’s httpCacheExpiration attribute in web.config. That sets the default Duration for a page. Continue reading “A Burst Cache implementation released”
Death by Background Thread Exception (including ThreadPool User Work Items)
If you use a thread or ThreadPool.QueueUserWorkItem to run code asynchronously and don’t catch your exceptions inside your WaitCallback, you will bring your entire application down when it breaks.
// This code snippet kills your web app process.
var ctx = System.Web.HttpContext.Current;
var u = ctx.User;
On the highlighted line, a NullReferenceException is thrown (because a background thread has no HttpContext). Continue reading “Methods of .NET self-annihilation part 4: Background Thread Exceptions”
This is another issue that results in Frequent Web Application Restarts, which causes the performance to plunge.
Death by Stack Overflow
This one is interesting, yet it has nothing to do with StackOverflow.com.
The StackOverflowException is one of very few exception classes in .NET that are not catch-able. Scratch that, it’s not possible to “swallow” it in a try-catch clause, because even if you don’t re-throw it, .NET will:
Starting with the .NET Framework 2.0, you can’t catch a StackOverflowException object with a try/catch block, and the corresponding process is terminated by default.
Continue reading “Methods of .NET self-annihilation part 3: Stack Overflow”
This bug appears only in load-balanced / remote events setups for CMS versions between 7.5 and 9.0.2 (released September 14th 2015, in which it was fixed). It’s reported as bug CMS-1405. This memory leak is relatively slow. Because of the way that ASP.NET handles cache, the application’s memory allocation will remain constant while the cache portion of it will continuously decrease ending up in an application with no cache at all. Continue reading “Memory Leak in CMS prior to 9.0.2”
Last post I discussed why Frequent Web Application restarts are bad. This is an issue that can cause you pain trying to get the application back up running again:
Death by IIS Ping
IIS’ built-in health monitoring is quite simple, but despite it having the word “ping” in its name, it has nothing to do with the network/ICMP type ping that we are used to.
Instead, what it does is that it queues a “ping” work item into the thread pool of the monitored application pool, and waits for it to be executed. Now consider the case where the application has restarted for whatever reason during peak hours and your users are lining up long waiting to get the first pages from the freshly started application. The IIS ping health check has to wait in the same line and if it doesn’t get its check executed within the time span, the application pool is deemed unhealthy and restarted. This doesn’t make the situation any better even by a tiny bit unfortunately, and you may be stuck having a seemingly never-starting process.
For every application, there’s a threshold where the inflow of new requests are low enough to allow the IIS ping check to be executed within the time frame given. This explains why you will be able to get the application up and running if you block incoming requests in the firewall for the duration of the startup, and then let the load back on.
Or, just disable IIS ping.
There are many different ways you may inadvertently kill your web application’s presence online. Here I try to list the major reasons an IIS site running .NET may underperform.
The trickiest cases to prevent are the time bombs. That code that runs really well in development, but starts misbehaving when put in production. Not immediately of course, but after a few months, making it really hard to track down which change brought the site under. I will get to those, but not in this post.
This post is the first in a series of posts. It describes a class of problems with the very descriptive name: Continue reading “Methods of .NET self-annihilation part 1: Frequent Web Application Restarts”
Today I was involved in an issue running the upgrade migration steps in Episerver Commerce.
This step is performed if you upgrade past Episerver Commerce 9.5.0 that came with update 94.
9:12:04 AM: Completed migration step: Migrate Property Decimal
9:12:04 AM: Failed to migrate property decimal: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The statement has been terminated.
9:07:04 AM: Starting migration step: Migrate Property Decimal
Continue reading “Commerce: Failed to migrate property decimal: Timeout expired.”
|This is a PageTypeBuilder specific post, so it does not apply to users of CMS 7+.
This post balances yesterday’s post which discusses the effects of caching. This one discusses the effects of not caching.
Consider the following code example:
[PageTypeProperty(EditCaption="Display Page Name", UniqueValuePerLanguage=true, Searchable=true, SortOrder=2, Type=typeof(PropertyString), Tab=typeof(InformationTab))]
public virtual string DisplayPageName
this._displayPageName = this.GetPropertyValue<PageTypeBase, string>(p => p.DisplayPageName) ?? base.PageName;
this._displayPageName = value;
See the class variable
_displayPageName? The variable that stores the value retrieved from the first non-null property of DisplayPageName and PageName. From reading that code, most readers would assume that the GetPropertyValue method is infrequently called.
Unfortunately, that is an incorrect assumption and the cache is practically useless. This is because the strongly typed PageData instances generated by PageTypeBuilder are never cached. Each time you get this page from the DataFactory, its class variables reset to their default values.
PageTypeBuilder hooks into Episerver CMS by attaching a handler to the DataFactory.Loaded*-events. Each time an untyped page is loaded from the cache, the LoadedPage event is fired and this line of code is executed:
static void DataFactory_LoadedPage(object sender, PageEventArgs e)
if(e.Page == null)
e.Page = PageTypeResolver.Instance.ConvertToTyped(e.Page);
The returned page instance is a new instance, with its properties populated by a cached instance. In the best of circumstances, the cache would be operational only for the duration of one page view, but I doubt it even works that well.
This applies to WebForms and MVC scenarios alike, but it’s mostly MVC users that are tempted in doing it: Never put request specific data into the ContentType model class! It may sound obvious to some, and not so obvious to others. Regardless, it’s an easy mistake to make. Worse is, doing it may survive development, QA, UAT… But NOT production use!
Just imagine the panic after just going live with your site and you get user reports that they occasionally see other user’s data, such as order confirmation pages, profile pages… Or that pages sometimes contain a mash from multiple users’ requests. Continue reading “Rule of thumb: Never have [Ignore] properties in a ContentType/model”
The French say “jamais deux sans trois”. If something happens twice, it will happen again.
Twice I have seen questions about why Episerver Find performs multiple/repeated requests to the Find index for its configuration (_config) when working to minimize the number of queries. Continue reading “Find _config requests”