ITQuants blog

Fusion Invest v7: How to optimize the refresh of the memory cache when portfolio columns are toolkitted

Dec 11

Written by:
12/11/2015 11:34 AM  RssIcon

In most cases, when portfolio columns are toolkitted, they use an internal memory cache to avoid SQL queries on the database when the portfolio lines are displayed (on scrolling or what ever). In order to refresh this memory cache, the Sophis API provides a method, CSRPortfolioColumn::GetRefreshVersion, which is incremented on some actions, for instance when a deal is inserted. Most toolkit implémentations use only this flag to refresh the cache. Unfortunately, testing only the version flag could generate some freeze, when a lot of a deals are inserted and SEC events are received. The goal of this post is to propose a solution in v7 to optmize the refresh of the cache.

The first thing that can be done is to test if the GUI is stll receiving SEC (Sophis Event Coherency) messages or not. In most cases, the current user is no interested to follow exactly what that can be done by other users. In a C# toolkit plugin, this can be done by including the Sophis.Core.Data.dll assembly as reference. This assembly contains the declaration of the SophisEventManager class, which permits to register an event Handler for listening events, or to send SEC events. Some actions can be used, like Start, Stop, and test if events are received by the GUI (AreIncomingEventsPending). This is this method that can used in order to disabling the refresh of the memory cache.

By the way, the test could be then the following one, in the overriden Sophis method of the CSMPortfolioColumn class:

public override void GetPositionCell(CSMPosition position, int activePortfolioCode, int portfolioCode, CSMExtraction extraction, int underlyingCode, int instrumentCode, ref SSMCellValue cellValue, SSMCellStyle cellStyle, bool onlyTheValue)
{
  int gVersion = GetRefreshVersion();
  if(gVersion!=currentVersion && !SophisEventManager.Instance.AreIncomingEventsPending)
  {
     currentVersion = gVersion;
     ClearCache(),;
  }
  ....
}

Even in this case, it could be not enough, and the GUI can freeze when the values displayed in the columns take too much time to be calculated. Another solution is to add a timeout in order to disable the refresh during a certain period after the last event received. A listener should be added as follow in the EntryPoint method of the toolkit assembly:

SophisEventManager.Instance.AddHandler(new SophisEventHandler(ITQ_EventHandler.HandleEvent), Sophis.Event.Thread.MainProcess, Sophis.Event.Layer.Model);

Where the ITQ_EventHandler class is declared as follow:

public class ITQ_EventHandler
{
    private static int m_lastEventTime = 0;
    public static int GetTimeout()
    {
        return Environment.TickCount - m_lastEventTime; 
    }
    public static void HandleEvent(Sophis.Event.IEvent myEvent, ref bool deleteEvent)
    {
        m_lastEventTime = Environment.TickCount;
    }
}

The test for disabling the refresh becomes then (timeout of 10s):

if (globalVersion != currentVersion && ITQ_EventHandler.GetTimeout() > 10000 && !SophisEventManager.Instance.AreIncomingEventsPending)
{
    currentVersion = globalVersion;
    ClearCache();
}

In this case, if a lot of messages are received during a long period, the GUI is not frozen, but values are not refreshed even if the user wants to see them. The solution is then to force the cleaning of the cache when he pushs F8 or F9 (calculation). This can be done by overriding the CSMGlobalFunctions and add the cleaning in the StartPortfolioCalculation method. Note that only one callback can be declared on this class. It means that if you have to clear several memory caches which were developed in several components, a supplementary mechanism should be added in order to call several callbacks. This subject will be treated in another post.

Search blog