Implementing Caching in the Stock Trader: The Position Module

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Enterprise Library information can be found at the Enterprise Library site.

patterns & practices Developer Center

On this page:
Scenario | Design of the Position Module | Caching Values to Isolated Storage | Proactive Caching | Asking the User for More Space in Isolated Storage

In this chapter, we'll discuss how caching was implemented in the Stock Trader V2 application. To improve the startup performance, the position module stores the user's position and their market history in isolated storage. At the end of this chapter, we'll discuss how the news module uses interception to transparently cache retrieved news articles to the in-memory cache.

Hh852717.note(en-us,PandP.51).gifEd Says:
Ed
                 When we started to build the Stock Trader V2, we knew that performance was a very important aspect of the application. However, it's difficult and often not very effective to optimize the performance of your application much beforehand. For the Stock Trader V2, we waited to make performance optimizations until we had actual performance and usage information.  <br />First, we focused on implementing the functionality of the Stock Trader V2. Using an early prototype of the application, we conducted usability studies and early performance tests. By looking closely at the usage scenarios of the application and comparing those to the performance tests, we identified the areas where caching and other optimizations would provide the most benefit. The result was an application that performed really well. </td>

Scenario

In the position summary view, the users get an overview of the stocks they own, their current market value, and their cost basis. When the user selects a particular stock, a graph displays the market history in a trend line and related news articles are displayed.

Hh852717.note(en-us,PandP.51).gifSharon Says:
Sharon
                From the usability studies we performed while developing the Stock Trader V2, we found out that most of our users start the application many times a day, to check up on the current value of their stocks. For these users, it was very important for the application to start as quickly as possible. <br />The second most used feature of the application is the trend line. As soon as they started up the application and noticed a change in the price of their stock, they wanted to see if this change is part of a trend. Users reported that it was annoying to have to wait until the trend line was loaded. They also reported that when they quickly change between stocks, the wrong trend line would sometimes be displayed.  <br />Lastly, a place where we found a performance bottleneck was in the news module. Whenever you select a stock, we also download and display the latest news messages. We found that most users will change the selected stock very often. This would cause way too much traffic when an important event in the stock market caused there to be many news articles. </td>

Design of the Position Module

The following diagram shows a schematic design of the position module.

Follow link to expand image

The position view, with its associated position view model, displays a list of the current account positions, with their current market values. The current account position information from the Position Service Agent and the current market value information from the Market Service Agent is aggregated and continuously updated in the ObservablePosition class.

The two service agents isolate the view models from all the details about how the particular information is being retrieved.

Hh852717.note(en-us,PandP.51).gifSharon Says:
Sharon
                 While building the Stock Trader V2, we isolated all interactions with web services in special service agent classes. This had the advantage of making our user interface logic much easier to test using unit tests. But it also provided us an isolated location for applying caching.  We only wanted to apply caching to places where it really improved the performance and user experience. Because we had isolated the logic for accessing web services in separate service agents, we were able to apply caching to the application without having to change the UI logic. </td>

Caching Values to Isolated Storage

The position service agent will cache requests for the current account position to isolated storage. Once this information is cached, the application would start much faster. Since the current account position data also contains the market value on the last closing day, we decided that we wanted to invalidate the cache at the start of the next trading day.

Proactive Caching

When the user selects a particular stock, the position view model will notify the market history view model to display the information for that particular stock. The market service agent will then asynchronously retrieve the information from the service. The market history only needs to be updated once a day, so by storing this information in isolated storage, the users can view the market history much faster after starting the application.

Hh852717.note(en-us,PandP.51).gifEd Says:
Ed
                 Our users reported a nasty problem with the market history trend line. When they quickly changed between different stocks, occasionally they would see the wrong trend line. After some examination, we found that this was caused by the market service agent. This service agent retrieves the market history asynchronously. When you select stock 1, it will start downloading the market history for stock 1. If you then quickly select stock 2, it will also start downloading market history for stock 2. However, if the market history for stock 1 has completed its download, it will begin to display. Only when stock 2 has completed its download will the market history of stock 2 be displayed. </td>

To solve this problem, but also to improve the performance of the trend line, a proactive caching implementation was developed. This means that the market history information would be downloaded and added to the cache on a background thread. When the user selects a particular stock and the market history is not yet downloaded for this stock, the market history for this stock will be downloaded as soon as possible.

The following diagram shows how the proactive cache works:

Hh852717.F1BBDBB214509AEA95BB40154BFCEEA0(en-us,PandP.51).png

At the core of the proactive cache is the DownloadRequest class. This download request has two actions: The StartDownloadAction, which will start the download if you call it. It can also have a DownloadCompleteCallback, which will be called when the download has completed. This callback is typically used by the user interface to detect that the download has been completed and that the data can be displayed.

The download request also has a CacheKey property. Before starting the download, the ProactiveCache will check if an item with that CacheKey is already present in the cache. If so, it will return the cached item directly. If the item with that cache key is not found, then the asynchronous download is started. After the download has completed, it will add the downloaded value to the cache under the specified CacheKey so any subsequent calls don't need to download again.

The proactive cache has two public methods: EnqueueDownloadRequest and GetData. The EnqueueDownloadRequest method will add download requests to the download queue, which will be processed by a background thread in the order received. The GetData method will add a download request that will be processed as soon as possible. This method will remember the last request that was added by the GetData method. Only for the last request will the DownloadCompleteCallback be called. This means if the user very quickly selects three different stocks, then the trend line view will only be updated for the last selected stock. The market history for other stocks will eventually be downloaded in the background, so if the user selects them later, the item can be returned from the cache very quickly.

Hh852717.note(en-us,PandP.51).gifSharon Says:
Sharon
                Proactive caching is a great technique for preemptively retrieving information that the user is very likely to use. When used in the correct places, this technique can improve the user experience. However, you should keep in mind that downloading information in the background can cause user-initiated downloads to be slower. It is also possible that you'll download more information than the user actually needs. This will increase the pressure on your back-end servers, so you should only use proactive caching where it really makes sense. </td>

Asking the User for More Space in Isolated Storage

When the Stock Trader starts, one of the first actions it performs is to check the isolated storage quota. If the isolated storage quota is set below 10 Mb, it will ask the user to increase it.

In Stock Trader V2, the logic to increase the size of the isolated storage quota is found in the IsolatedStorage service class. This class has methods to query the isolated storage size, and to ask the user for a larger quota. Asking the user for a larger quota must always occur as the result of a button click. In other words, you will need to display a custom message asking the user for additional quota. This is the dialog box that the Stock Trader shows to ask for an increased quota:

Hh852717.B030832562DE0349E612AF98EF27F0EC(en-us,PandP.51).png

If the user agrees, then you can call Silverlight to try to increase the quota. This Silverlight dialog box will ask the user to increase the quota, and if the user agrees, then the quota is increased.

Follow link to expand image

The following code example shows how you can increase the size of the isolated storage quota:

IsolatedStorageFile isolatedStorageFile;
// Use the Quota property to find out what the current quota is. 
long quotaInBytes = isolatedStorageFile.Quota;

// Use the IncreaseQuotaTo method to ask the user to increase the quota. 
long newQuotaSize = 10*1024*1024; // 10 Mb
bool increased = isolatedStorageFile.IncreaseQuotaTo(newQuotaSize);

Next Topic | Previous Topic | Home

Last built: July 8, 2011