Episerver CMS performance optimization – part 1

This is an unusual post – it is not about Commerce – my area of expertise, but about CMS. Recently I’ve been working on some support cases where SQL Server instance is on high utilization, and in some scenarios it eventually slows down the site. After investigation, it’s likely to come from a small, simple and helpful feature: Simple address.

CMS content can have a property named “Simple address”, which allows you to create a “shortcut” url for that content. So if you have one page with “name in url” as “contact-us” under a page name “about-us” under Home page, you can access it via https://mysupercoolsite.com/en/about-us/contact-us. Or you can set the Simple address for that page as “contact-us”, and then you can access it directly via https://mysupercoolsite.com/contact-us.

Changing Simple Address in Edit UI

Now it’s an interesting part: To make the simple address concept work, Episerver has to call a special stored procedure (“netquicksearchbyexternalurl” if you wonder) to check if any published content has that simple address (“ExternalUrl” is the field internally). If a content is not found, a 404 error will be shown.

Sounds reasonable, right? But that small and handy feature can come with a drawback: performance!

What? Why? How?

The simple address is the first router to be registered by Episerver – so it will also be the first one to process all URLs (except for static files for example, of course). To see which URLs are being processed by Simple Address – let’s play a bit. Note that this is highly experimental so you should not try it on production (You’ll likely not to, but I feel obliged to say). Let’s add a table to track all requests to  netquicksearchbyexternalurl

And modify the stored procedure itself to insert to that table whenever it try to resolve an url:

That’s all. Now just try to visit the website. There are the requests SimpleAddress router handled when I just browse around Quicksilver:

You can see many of them are clearly not simple addresses – they are assets or catalog content. However, all of them will be queried against tblPageLanguage. The router for Simple Address has cache internally, but if you have enough requests, it’ll soon fill in the cache and trigger the cache trimming, therefore the view will be queried again. Even worse, if you have enough rows in tblPageLanguage, each query will take more time and resource – tblPageLanguage (and its underlying tblContentLanguage table) contains information for all CMS Content (Pages, assets, etc.) so it’s easy to have quite big size (The one I investigated has 3.7M rows). When you have a lot of queries which are not super fast to run, it’s only matter of time before it bring your SQL Server instance to its knees.

netquicksearchbyexternalurl under spotlight. You won’t want to see this, of course

Is there a solution for this problem? Yes. If you don’t use Simple Address at all, just disable the router, and it will save you from queries after queries. This simple code in an InitializableModule will do that:

This will remove SimpleAddress from the registered routes, and it will trouble you no more.

It's only fair to share...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInShare on Reddit

7 thoughts on “Episerver CMS performance optimization – part 1”

  1. Hi Quan

    Great job. Very nice article.
    Exciting and nice to know the limits and bottlenecks of the system/solution.

    Sadly though, I have a marketing department above me, calling the shots. They are determined that SimpleAddress is the way to go, due to visibility and branding through deeplinks.

    Not that is matter in this specific case, but could you include the EPiServer version in your future posts, for reference?
    We’re on the verge to start updating, and it would be neat for me to know whether the information could be relevant as we move forward.

    Have a nice day.

    Best regards,
    Henrik C. Jensen

    1. Hi Henrik,
      When I think a post only applies for a specific version, I will mention it. If I don’t then that means it applies for a good range of version – include the most recent one. (I’ll update if future version changes that)
      It should be able to move the SimpleAddress to the last in the router list. I filed a bug for CMS Core team so they can look into it.

  2. Good post. Most marketing departments I’ve worked with make heavy use of the simple address feature (its main use case being shorter urls to put on printed materials).

    If disabling isn’t an option, it looks from your investigations that there is a fair bit of optimisation that Episerver could add to the core implementation that may help large sites where the cache is trimmed.

    Why go to the database at all if the path is one of the known / reserved keyword routes (such as ~/globalassets or ~/episerver). I’m presuming that this also tries to match any static routes as well, so why not provide a initialisation API where I can tell the simpleaddress router to ignore any requests for directory that I know are not simple addresses.

    Mark

  3. I moved my simple address route to be last. Works great! 🙂
    Makes sense to have the most common routes resolved first and then in descending order. There are usually very few simple urls on a site and seldom much traffic to them so makes sense to keep it among the last ones. If nothing else to save some memory since it doesn’t have to store every possible url in cache for the episerver site…

  4. Could we change the SimpleAddress router order to last routing due to we need to use SimpleAddress function 🙂

    1. Technically you can – RouteCollection is inherited from Collection so you can remove and re-add it (to the end)

  5. This is a great post indeed, but I have to agree with some other guys here.
    Rather than just removing simpleaddress you should absolutely move it last in your routecollection.

    If you are 100% sure you’ll never use it then it’s fine to remove it, but more often than not marketing people will require the feature.

    Moving it last in my routecollection made a huge difference on our performance, that should be your number one go to solution.

    Great article though, and it’s very well written 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *