EPiServer, Episerver 11, Performance

Episerver block performance: with controller vs without controller vs IRenderTemplate

What is the performance difference when using Episerver block without controller or with controller or with a custom IRenderTemplate<T> ? When should you use controller for a block and when you shouldn’t?

I was having fun with my friend Google and found a blog post by Episerver EMVP Erik Henningson: “Performance when using controllers for blocks“. Erik had done some benchmarking for blocks and his testing showed 7 – 15% difference in favour of block without a controller and his conclusion was he tries to avoid controllers with blocks when possible. I totally agree that we should avoid controllers with blocks when it is reasonable.

I’ve used the following rule of thumb with blocks:

  • if the block model is all you need in the UI, don’t add controller because all you do in the controller is take the block data and pass it as a model to the view
    • instead have your block model and have just a view for the block (view has the block type as its model)
  • if the block has data and “configuration parameters” for functionality then use controller, sample of such could be “latest news block” where editor might define how many news items are displayed, title for the block and link to all news
    • here it is the controllers responsibility to create the view model for the view to consume and the block data itself isn’t sufficient
      • we might create a view model where one property is the block data
      • another property is the “list” of the latest news that the controller has fetched from our news service

So what can I add to Eriks posting? Well when Episerver 7 was released many moons ago they realized that blocks with controllers had a negative impact to performance and we partners were instructed to think twice do we need controller for a block. So what I’m adding to the performance test is the IRenderTemplate<T> custom implementation blogged by Episerver Jonas Bergqvist: “Hidden template functionality in the MVC implementation“. This is old post but I’ve used this approach in some cases and it still works with Episerver version 11.

Setting up Episerver project to do the benchmark comparision

So I was purely only interested about how the block performs so no Alloy this time. I created an empty Episerver project and added two page types: start page and a content page with a content area. The start page renders links to its children so that I can easily navigate to the test pages done with the standard page type. No menu on the standard page, nore any result filters in the whole solution. No ASP.NET MVC layouts each page has their minimalistic valid html structure. No CSS or JS resources. Really simple and plain.

Next I implemented the IRenderTemplate<T> from the blog post by Jonas. Only change to the code was the comment I had made to the blog posting (4th of April 2014 :D) after having a mail conversation with Jonas and Johan Björnfot back then. Here is the ViewRenderTemplate for your convenience.

block-perf-render-method
Render method change to the original code as the Episerver routing was changed

Next I created three different blocks with a single string property named ‘Text’ to test the performance cases: without controller, with controller and with the rendering template.

block-perf-text-block
Really simple block with a string property

And then I created a controller and view for one of the text block implementations and another “controller” inheriting from the “ViewRenderTemplate<T>” and a view for this and lastly only a view for the block without controller.

Benchmarking

I like to use tool called ‘bombardier‘ to stress test someting.

I used my home desktop PC to do the benchmarks:

  • Intel Xeon e3-1231 v3 @ 3.4 GHz (Max turbo frequency 3.8 GHz under load, actually boost to something like 3.59 GHz when all cores are 100% under load)
  • 16 GB RAM
  • SSD disks
  • Windows 10
  • IIS Express was used
  • MSSQLLocalDB was used
  • Release build was used

Tests that I run with bombardier were using 50 clients and making 100 000 requests. I also tested with using 10 clients and 100 000 requests just to see if it makes any difference to use less clients. Obviously the CPU was at 100% during the tests 😀 There were no noticable difference in the memory usage but I didn’t use any actual analyzer but just looked at the Windows 10 task manager performance tab. Enough scientific for now 😀

Episerver pages:

  • page having one text block without controller
    • another page having 5 text blocks
    • another page having 10 text blocks
  • page having one text block with render template
    • another page having 5 text blocks
    • another page having 10 text blocks
  • page having one text block with controller
    • another page having 5 text blocks
    • another page having 10 text blocks

Episerver blocks:

  • I had 10 instances of each different block type

Summary of benchmark results

So benchmarks with bombardier were executed with 50 client and 100 000 requests.

One text block in content area

  • with controller
    • elapsed: 35 seconds
    • avg requests/sec: 3027.91
    • throughput: 3.88 MB/s
  • with ViewRenderTemplate
    • elapsed: 32 seconds
    • avg requests/sec: 3312.45
    • throughput: 4.25 MB/s
  • without controller
    • elapsed: 32 seconds
    • avg requests/sec: 3236.15
    • throughput: 4.33 MB/s

With just one text block there is not big difference in the elapsed time but roughly 6.8% difference in avg requests/sec with controller VS without controller. I would say it was some sort of glitch in the matrix that ViewRenderTemplate avg requests/sec was better than without controller.

Five text blocks in content area

  • with controller
    • elapsed: 1 minute 12 seconds
    • avg requests/sec: 1616.62
    • throughput: 5.26 MB/s
  • with ViewRenderTemplate
    • elapsed: 55 seconds
    • avg requests/sec: 2010.61
    • throughput: 6.98 MB/s
  • without controller
    • elapsed: 53 seconds
    • avg requests/sec: 2372.06
    • throughput: 7.12 MB/s

With five text blocks in the content area there starts to be a difference in the total execution time and without controller we get roughly 46.7% difference in the avg requests/sec. So at leasts looks like the more you have blocks in the content area the more you start to pay for using controller for a block.

Without controller VS ViewRenderTemplate is roughly 17.9% difference in av requests/sec in favour of “without controller”.

With controller VS ViewRenderTemplae is roughly 24.3% difference in favour of ViewRenderTemplate.

Ten text blocks in content area

  • with controller
    • elapsed: 1 minute 46 seconds
    • avg request/sec: 1317.80
    • throughput: 6.21 MB/s
  • with ViewRenderTemplate
    • elapsed: 1 minute 22 seconds
    • avg requests/sec: 1375.53
    • throughput: 8.89 MB/s
  • without controller
    • elapsed: 1 minute 21 seconds
    • avg requests/sec: 1415.27
    • throughput: 8.98 MB/s

Finally the ten blocks tests, there is roughly 24 seconds difference block with controller VS without controller and ViewRenderTemplate in the overall execution time.

As we look at the results with ten blocks we can see that the avg requests/sec almost drops to half compared to five blocks test case but the dfiference with the implementation is not so dramatic as was in the five blocks test case.

Now the difference with without controller and with controller is “only” 7.3% when comparing the avg requests/sec.

If we look at the total time and throughpput there is quite big difference in favout of the ViewRenderTemplate and without controller tests – maybe this could be explained how the bombardier calculates the avg requests/sec or something else. When running this test with only 10 clients but 100 000 requests there was again 30% difference in the with controller VS without controller avg requests/sec.

I also did run similiar tests with Netling but it doesn’t use the same configuration to run tests as bombardier. Netling takes arguments on how many threads to use and for how long to run the tests. For Netling I used the “elapsed” times from bombardier runs and clients == threads.

Conclusion

Scroll up and read again my rule of thumb 😉

I’ll include here the actual command line out puts from bombardier and netling runs so you can have a look at the details.

I think I need to do another test between block with controller VS using the ViewRenderTemplate and having a custom view model and some actual work in the “controller”.

Advertisements

3 thoughts on “Episerver block performance: with controller vs without controller vs IRenderTemplate

  1. We use controllers for all our blocks but we also have our blocks using output caching with dependencies on content changing in the CMS using the “currentBlock” output cache mechanism and the ISynchronizedObjectInstanceCache. This works very well from a performance point of view as your skipping any viewmodel creation logic and the rendering of the view itself as it’s just serving up the cached version.

    1. Hi Scott and thank you for the comment. The point of the post was to show the “raw” comparison of different ways we can render blocks so caching strategies was out of the scope.

      As you know with caching (but other readers might not know) there are challenges when personalized content is used. Episerver includes the implementation for ContentOutputCacheAttribute ( https://world.episerver.com/documentation/class-library/?documentId=cms/11/47171707 ) which has its limitations and criteria when it is used.

      Scott I’m not sure if you have blogged about the implementation you have used but in case you haven’t, you should 🙂 Post a comment with link to your blog post here.

      In the meanwhile others can read about “Russian doll caching” blog post by Johan Björnfot: https://world.episerver.com/blogs/Johan-Bjornfot/Dates1/2017/12/html-caching-in-redis/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s