High Performance Pages in UCM and Site Studio

There aren't many things that you can say every customer wants in a web site or web app, but I think one thing everyone agrees on is they want it faster. Since UCM is a web application running on Java, a lot of tuning you do for those applications apply here. JVM tuning, database tuning, web server caching, etc. Brian "Bex" Huff recently did a webcast presentation on "Site Studio Performance Tuning" through the Independent Oracle Users Group (IOUG). Unfortunately, I wasn't able to attend. But I'm sure he covered a lot of those topics.

One topic that I'm guessing he covered is on Idoc Script caching. It's a handy trick that isn't used in any of the standard resources or templates, so not sure how many folks know about it. But it's a great way to get way to get a big performance boost at a little price.

Basically, it's a function that works much like the <$include ...$> does, but will cache the results of that include for a specified amount of time. So if that includes does a lot of service executions, parsing, or is generally an intensive operation, the server will cache those results and ease work on the CPU and possibly database.

<$cacheInclude("my_include", "application", 120)$>

The first parameter of the function is the name of the include you're calling. The second parameter is the scope of the cache. If it's set to application, then it's globally cached for all users. If it's set to session, then it's cached only for that user. So if you're include is going to have personalized or security based content, you can at least cache it for that user. And the third parameter is for the time in seconds to cache the include. There are two more optional parameters (cacheName and key) that is further detailed in the Idoc Script Reference Guide.

If you're working in components and modifying the UCM interface, it's easy enough to write your includes right within the component. But if you want to make use of this function in Site Studio pages, it's not as convenient to work in components. So what you can do is define your includes in an .idoc file, check it in, and reference it using the <!--$docLoadResourceIncludes( ...--> function. Then you can call the includes as if they were in a component. One thing to note is when you move code out of Site Studio and into an .idoc file, the syntax for the idoc changes to the <$...$> format. That's because Site Studio pages (.hcsp) are indexed and .idoc ones are not.

Here's an example to test it out:

1. Create a text file named cache_includes.idoc and put in this code:
<@dynamichtml display_time_global@>
Time this fragment was rendered and cached:
 <$formatDateWithPattern(dateCurrent(),"HH:mm:ss Z")$>

<@dynamichtml display_time_user@>
Time this fragment was rendered and cached for user <$dUser$>:
<$formatDateWithPattern(dateCurrent(),"HH:mm:ss Z")$>
2. Check in the cache_includes.idoc file and set the Content ID to be 'CACHE_INCLUDES'

3. Create a text file named cache_test.hcsp and put in this code:
<!--$cacheInclude("display_time_global", "application", 120)--><br/>
<!--$cacheInclude("display_time_user", "session", 120)-->
4. Check in the cache_test.hcsp file. Now if you click on the link, you'll see the results like:

Time this fragment was rendered and cached: 08:41:16
Time this fragment was rendered and cached for user sysadmin: 08:41:16

Log in as another user and they'll see the results as:

Time this fragment was rendered and cached: 08:41:16
Time this fragment was rendered and cached for user larry: 08:41:31

Another trick when using this with Site Studio is you may want to avoid the caching when in contributor mode. To do this, you simply add a check for SSContributor and if true, use the standard includes:
<!--$if isTrue(SSContributor)-->
  <!--$include ...-->
One way to measure the improved performance is to go to Administration -> System Audit Information and in the Tracing Sections Information, select 'pagecreation' from the list for Active Sections. Then click on View Server Output, Clear, refresh the page you want to measure in another browser, and then refresh the output. For one customer I helped with this, they were getting page creation times of up to 2 seconds. Adding the caching brought it down to 10-20 milliseconds! When you have lots of users accessing the system, that change can make a big difference.

Good post!! Are there any posibility to invalidate the cache using services, idocscript o java when one "include" is cached ? Thanks.

Posted by Alex on October 20, 2009 at 06:19 PM CDT #

Hey Alex, Ah, I should have included that. Yes, there is a function dedicated to invalidating that case. forceExpire(includeName, scope [, cacheName, key]). So you can invalidate specific resources or if you leave the first includeName value blank, it will invalidate them all. So you could add a section to the page which checks for a certain value being passed in and if present, it calls this function which would expire the cache. That way you can simply call a URL to do the invalidating of the cache.

Posted by kyle.hatlestad on October 21, 2009 at 03:16 AM CDT #

Hi Kyle, am an system administrator for an UCM instance. With user writing idoc scripts, how can we gauge the performance of these scripts from a sysadmin point of view. We had an occasion where a user added an idoc script which was consuming large memory and crashing JVM, probably in a loop. How can we proactively identify these scripts and find out the performance impact. Any suggestions ? thanks, Venu.

Posted by Venu Puli on July 15, 2010 at 06:17 AM CDT #

Hey Venu, Unfortunately, there is no way to test or validate the scripts without running them on the server itself. My suggestion would be for these scripts to be created on a development system that would not have as a big an impact if they were affected this way. Then to be migrated to the production system. Thanks, Kyle

Posted by kyle.hatlestad on July 16, 2010 at 01:10 AM CDT #

Hi Kyle, Would there be a way to do this on pages that execute the SS_GET_SEARCH_RESULTS service? I would imagine that you would place the executeService call within the cache_includes.idoc from your example, along with all supporting variables and settings. Would this be considered a correct implementation?

Posted by Ed on August 05, 2010 at 06:27 AM CDT #

Hey Ed, Absolutely! That's exactly the type of use-case that it's for. Any time you are running the executeService call within a page, that has the application do additional work (often with SQL or search queries) which can lead to additional processing time. If you roll that into a cache include, the server no longer has to do that work every time. Just be aware that when caching search results, if you expect those results to be secure and in context of the user, you need to scope the cache to be for that user and not for the application. But if it's public content and consistent for everyone, then scoping it to the application will add a lot of benefit.

Posted by kyle.hatlestad on August 05, 2010 at 11:48 PM CDT #

Hi Kyle What about put a whole hcsp page into the .idoc file anc use cacheInclude to include it? Is it possible and useful? THanks

Posted by Guang on October 17, 2010 at 11:45 AM CDT #

Hello Guang, Yes, you could include all the logic that would be contained in a .hcsp page and roll that into an .idoc file and call that as one large resource with cacheInclude. Just keep in mind that you would need to convert all of the hcsp idoc format with

Kyle Hatlestad is a Solution Architect in the WebCenter Architecture group (A-Team) who works with WebCenter Content and other products in the WebCenter & Fusion Middleware portfolios. The WebCenter A-Team blog can be found at: https://blogs.oracle.com/ ateam_webcenter/


« April 2014