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
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.