Caching display methods in forms

This post is probably not the most earth shaking news but still a relevant issue to visit once in a while.

When developing or customising forms we often have to put in display methods to show the user data not available directly from the datasource. That can be either data from related tables or the result of calculations. For each refresh of data the display fields will be updated and the content recalculated. This can result in a significant performance plunge which easily can be fixed.

I did a quick test and in the Customer group form with 7 records a display method is called 27(!) times just opening the form. If your display method is the first column in the grid you can actually add a couple of clicks to that number.

So there definitely motivation enough here to spent a few moments on this. So let us start by separating the display method into two categories: Form methods and table methods.

Caching table methods

This is the easy one. Go to the init method on the datasource and add the following piece of code after the super() call:

CustGroup_ds.cacheAddMethod(tableMethodStr(CustGroup, cacheTestTableCached));

That is it. Your table display method is now cached and in the above example goes from 27 to 7 clicks.

Caching form methods

In this example we have a display method on the CustGroup datasource looking like this:

display Description paymTermDescription(CustGroup _custGroup)
    return PaymTerm::find(_custGroup.PaymTermId).Description;

With the earlier mentioned example this data lookup will be performed 27 times for 7 records. Here we need to do a couple of lines of coding to do make this work. First of all we need a Map object in the form declaration method:

public class FormRun extends ObjectRun
    Map cacheDemo;

Then we change our display method to look like this:

display Description paymTermDescriptionCached(CustGroup _custGroup)
    if (! cacheDemo)
        cacheDemo = new Map(Types::String, Types::String);
    if (! cacheDemo.exists(_custGroup.PaymTermId))
        cacheDemo.insert(_custGroup.PaymTermId, PaymTerm::find(_custGroup.PaymTermId).Description);
    return cacheDemo.lookup(_custGroup.PaymTermId);

Let us break down what the method does now.

  1. First we make sure that the Map object cacheDemo is instantiated. This could be done in the forms init method instead.
  2. Then we check if we already have the value we need in the cache. This is done based on the PaymTermId field on the CustGroup record. If it is not found we add it to the cache.
  3. Finally, we lookup the value from the cache and returns it. We know that the value always is in the cache so no need to do an exists check again.

This means that we still hit the display method as many times as before; but the calculation/data search part is only executed once per Payment term id. In this case that makes it 6 clicks since to customer groups had the same Payment term id.


Leave a Reply

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

You are commenting using your 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 )

Connecting to %s