Knowledge Base (Display) Knowledge Base (Display)

Document & rendering caches

Document & rendering caches

This article explains how the two main reportlet caches work, it is very important if you plan to use Visioneo reportlet in your project. However you don't have to understand all chapters right now: primarily you just have to know how to adjust a cache expiration to fit your requirements ("Configuration" chapter), how to share caches across users or not  ("Sharing caches between users" chapter), and how to manually refresh caches when necessary ("Dynamic control" chapter). You will understand the other sections little by little! 

1-Definitions

2-Performances

3-Configuration

4-Storing & cache size

5-Sharing caches between users

6-Cache & request localization

7-Cache & report width / height

8-Render-only parameters

9-Organize the system hidden parameters

10-Parallelism

11-Dynamic control

 

Definitions

In a portal context, you can't afford make your users wait long seconds each time they apply any action. This is why this cache mechanism has been designed in the very early stages of the project. Typically, before generating a report the reportlet is checking if it has not already been generated in a former request, and if it is not yet expired.

  • The rendering cache is the first reportlet cache level. A rendering cache entry is the final report output displayed in a reportlet window, and its dependencies (mainly the charts images). When this cache can be used, it allows ultra-fast report renders. 
  • The document cache is the second reportlet cache level, it is used only when no rendering entry is available for requests. Basically a document cache entry is a birt 'rptdocument', which is a kind of intermediate binary format used by Birt before rendering a report. Each time a Birt engine generates a 'rptdocument', it is compressed in memory by the reportlet and stored in the document cache. 

Both rendering and document caches are managed with the leading caching solution Ehcache.

Performances

The orders of magnitude below are extracted from the visioneo live demo environmment, they may obviously vary depending on your context. In particular, the report generation time without any cache is completely subjective: it depends on your data sources, latency, report size & complexity, the design quality,  etc.

If most of your reports last more than a certain time when none cache is used, you should probably change something in your architecture. Visioneo caches will greatly help you, but can't do anything on a first report generation! There are many ways to optimize Birt reports: add more filters/parameters, aggregate in sql queries rather in birt reports, using aggregated/de-normalized tables, stored procedures, more indexes, a columnar DBMS, etc. 

Caches Report generation time  per minute/processor core
No cache used from 1s to 5s about 20 reports
Document cache from 250ms to 1s about 100 reports
Rendering cache  from 30ms to 60ms (*) about 1000 reports

 

 s=seconds     ms=milliseconds  

(*) Time when the related cache entry is already in memory. If the entry is stored on the ehcache temporary disk space, the rendering values are slightly increased (generation time from 50ms to 100ms)

Configuration

 These caches can be fully customized in ehcache.xml file, which is located in the WEB-INF folder of your reportlet application.  You may decide here if a cache is "eternal" or not, disk persistent or not, set an expiration time, the maximum memory that can be allocated, etc.

In this file, the most important thing to setup is the expiration time for visioneo.documents.cache and visioneo.rendering.cache. The default value is 14400 (4 hours). For instance If you need (nearly) real-time data, you could consider to set this expiration time to 600 (10 minutes). You should not set a value lower than 600.

The expiration time is a key feature for scalability considerations and the user experience quality. Don't set a tiny value if your data sources are refreshed once a day!

It is of course possible to set different expiration time values for these 2 caches, you must follow this rule:

  Expiration(document.cache) >= Expiration(rendering.cache) >= 600

Note the professional edition will allow to set up the cache expiration time directly in the reportlet preferences mode. As a consequence, you will be able to setup if necessary a different expiration time for each reportlet window. 

Storing & cache size

Basically the document entries generated by the visioneo demo reports, once they are compressed, have an average size of 60 Kb. For the html rendering entries, it is about 20 Kb. Thus, for example  if you decide in ehcache.xml to allow 1000 document entries and 1000 rendering entries in memory, it should consume about 1000*0,06+1000*0,02 = 80Mb in your JVM Heap memory.

In addition to html outputs, the rendering cache stores exported files as well (PDF, Excel, Word...). This is a great feature, however although exported documents are compressed in memory before being cached, it is significantly increasing the average rendering entry size.

Default reportlet values are 100 entries for documents and rendering entries, you should increase these values in your context.  Make it with cautions, don't forget JVM memory heap size is constrainted by Garbage Collector duration.

When the maximum memory allowed is reached, the default ehcache.xml is setup to allow to write on a temporary disk space. Don't worry, even when ehcache needs to retrieve an entry from the disk, it is still very, very fast! However for a very large context, you could consider to use the fantastic Terracotta 'BigMemory' option. It is now possible to get a free license key from Terracotta, to manage in-memory caches upto 30Gb! 

Note exported files with a size higher than 20 Mb (before compression) are not cached. 

Sharing caches between users

 It is probably the most important thing to know about the document and the rendering caches: By default, cache entries are shared between all users. If 10 users request the same report, with exactly the same parameters values, they all use the same cache entry. This is obviously a major feature for your project scalability. If you wonder what happens if in addition all requests are simultaneous, this point is covered in the 'Parallelism' section below.

Some reports must be user specific, particularly for data security considerations. For example you may utilize the user id in your report main datasets.  When a report is user-specific, we must warn the engine by adding a report parameter. Please refer to the article Using portal attributes for more informations.

 

Parameters datasets (i.e. datasets used to produce a dynamic list in a combobox, for example) are not concerned by the cache mechanism. 

Cache & report width / height

This section is deprecated. From version 3.1 SVG charts are automatically resized

Your reports can use the reportlet window size to adjust some report items. It is overall useful for charts: in visioneo report samples, the radar chart and the breakdown sales chart use current window width and height to automatically adjust their size. Furthermore, the breakdown sales chart displays a title only if the width is sufficient. It can be achieved with a very simple javascript code in the 'onRender' event of the chart, have a look in the birt designer on the relevant .rptdesign files for a concrete example.

Once again, to use this feature in a report we must declare hidden parameterst: __width and __height. This is of course facultative, and you should not add these parameters when they are not used in a report. Once declared in a report, the reportlet populates automatically the values, and they can be used in report scripts like any other report parameter:

params["__width"].value

params["__height"].value

Render-only parameters

Although rendering parameters are not deprecated, this property requires a high understanding of BIRT mechanisms and its use is not recommended. You should ignore this section.

Most of the time, __width and __height parameters are only used at render time: whatever the report size, the datasets and the report general layout won't change. Therefore it would be clunky to generate a new report each time the dimensions change.

For example, when a user is switching between a standard/maximized view, it would be a shame to wait long seconds just because the report is now maximized. A feature has been implemented for this kind of requirement: it is possible to specify that a parameter is only used at render time, by adding to the parameter(s) concerned a specific user property:

__rendering=true 

In the Eclipse Birt designer, the user properties can be set in the advanced properties dialog:

If the __width and __height parameters have this specific user property set to true, then whatever the reportlet window dimensions the same document cache entry is used.  Therefore, if you render a chart report and then maximize it, the maximization will be very fast.

Another simple example: let's assume a user A includes in his private page a chart report with a size 800*600, and user B includes the same chart report with a size 500*350.  With the __rendering option, they share the same document cache entries!

Organize the system hidden parameters

This section is deprecated

As we have seen in this article, the reportlet engine is using several specific facultative parameters to decide when it should generate a new report, or get it from the cache:

  • __width
  • __height
  • <your own security parameters>

A good practice is to create these parameters once and for all in a birt common library. You can even use the visioneo-commons library included for the demo reports, and drag&drop the parameters you need in your reports.

Parallelism

Visioneo reportlet takes advantage of the Terracotta 'blocking caches' to implement a fantastic parallelism management feature. if a report is run several times simultaneously, with exactly the same parameters, then the report threads involved are synchronized!

Only the first report request is generated, the next threads will directly get the result from the cache generated by the first thread. For example, if a user runs a large report, cancels it and runs it again, the second call will just wait for the first report has been generated, and then get it from the cache.

This feature is very powerful, and incredibly important for scalability considerations. Furthermore, if a pending report is "sleeping " more than 120 seconds, then the thread is stopped and an exception is thrown to free the reportlet window such: 

Error when processing the export resource: report <report name> Lock timeout. Waited more than 120000ms to acquire lock for key.

Of course, this feature does not concern requests addressing different reports or different parameters values: all Visioneo requests are highly parallelized. This section only concerns strictly identical requests, such illustrated below.

 

 

Dynamic control

The best way to refresh the caches is to let the expiration time do the job. However, you may need to refresh them on demand, for example:
  • One of your report design has just been modified
  • Your data have just undergone an exceptional batch ...

If your application server has the JMX services enabled, it is possible to control dynamically the caches through the java console (remove all entries, check some statistics, change the configuration, etc.):    

 

If you can't enable the JMX services, it is possible to refresh the cache entries through the visioneo reportlet toolbar, when logged as an admin user. 

 
Tags: architecture admin
Average (0 Votes)
Most Recent
Toolbar portlet 01 April 2015
First admin steps 04 March 2015