There are some cases when data from infotypes are used very often and in very large scope i.e. for some statistical calculations before presenting some information. Situate this in some application, multiply by large number of users, add high frequency of usage and we have nice recipe for huge amount of database operations. When thinking about performance improvements in this scenario first thing that comes to mind is buffering – we can use, for example, some intermediate table with aggregated data, but I want to discuss usage of Shared Objects for this case.
The main idea is to setup buffer and update it only when necessary – this means only when data in specified infotype were changed. So whole mechanism have 2 parts:
1. In-memory buffer.
2. Trigger for buffer update.
The buffer is realized by Shared Objects and for the trigger we can use customer exit EXIT_SAPFP50M_002 (additional checks) which is used when data are changed via PA30 or function module HR_INFOTYPE_OPERATION. We can also use dynamic action or additional PAI module. Below are some details about this concept – for guide about Shared Objects search SDN or read topic page on help.sap.com.
Shared memory area as a buffer.
The buffer is implemented as shared memory area with 2 helper classes – loader and broker. Loader is responsible for creation of shared memroy instance and is used as a constructor class – this makes our shared memory preloadable which means that it will be constructed at first read. For high-availability scenarios (read area while it is updated) consider enabling versioning.
Constructor in loader class must satifsy interface IF_SHM_BUILD_INSTANCE and BUILD method contains code for setup shared memory. This is the moment where needed data is gathered, calculated, stored in internal table etc.
The broker class is a proxy for getting data from buffer – it provides methods for returning requested data from shared memory area. It should raise an exception when something went wrong i.e. memory area was under construction – catching this kind of error give us oportunity to get data in old fashion (directly from database).
Triggering buffer’s update.
Ok, we have our data in shared memory area. Now, we have to refresh buffer when infotype data holded in buffer have been changed. All we need to do is use invalidation mechanism – thanks to making our area preloadable, when we call invalidate method, the area’s construction will be started again.
For example – in EXIT_SAPFP50M_002 we can put this:
CASE innnn-infty. WHEN '2001'. CALL METHOD zcl_shm_example_area_loader=>refresh_buffer.
You can limit in user exit when refreshing should take place – when adding, updating or deleting infotype.
Using shared memory with user exit it is possible to implement simple or sophisticated buffer – with whole range of programming techniques (object ABAP inside Shared Objects model) and variety of control (conditions in exits).
Summarazing, below is the simplified flow of this mechanism:
Before first use, shared memory area instance not exists – when we call a method from broker class requesting buffer data, it tries to attach to read our area. Because it is marked as preloadable, it calls build() method from loader class. Area is constructed, needed data from infotype are selected, aggregeted etc. and returned to application. I next calls, buffer is returned from shared memory. When data on buffered infotype have been changed, a method for buffer refresh is called from user exit. This method invalidates shared memory area, so it runs build() method again, reloading needed data.