App preload - a cache warmer

App preload illustrates how the Qlik Sense .NET SDK can achieve fast load times when large apps are opened in the client for the first time. The engine caches all computations it performs. This means that if it is asked to do the same computation twice, then the computation can be expensive while the other will simply return the result from the first.

A typical scenario where app preload is useful is in a server environment where a large app resides. The first time a user opens the app, display of visualization components can take quite a long time since the engine has to perform all computations from scratch. It will, for instance, have to execute all hypercube computations and return data from them. When a second user opens the same app, the engine will not have to redo all the computations. It can simply return the results of the computations performed when the first user opened it.

The idea behind this sample is to trigger the initial computation by using the Qlik Sense .NET SDK instead of letting the first user accessing the app take the performance hit. An administrator might choose to run such an app preload every time a reload of the data for the app is performed.

We recommend that you to download and run the appropriate example before you continuing reading. All the sample code for the connection examples are available on Github.

Note: The purpose of the sample code provided by Qlik is to demonstrate capabilities and use cases of the API. They are provided on an as-is basis, without any guarantees that they will work in all system configurations and future software releases. These code samples are released under: Wikipedia: MIT license.

To reload the cache with computations for an app, do the following:

  1. Get all generic objects of the app.

    To get all generic objects of an app, it is necessary to recursively traverse all children of all sheets of the app. The following lines performs this operation:

    var sheets = app.GetSheets().ToArray();
    var allObjects = sheets.Concat(sheets.SelectMany(sheet => GetAllChildren(app, sheet))).ToArray();

    These operations rely on the following recursive function for traversing the object tree:

    private static IEnumerable<IGenericObject> GetAllChildren(IApp app, IGenericObject obj)
        var children = obj.GetChildInfos().Select(o => app.GetObject<GenericObject>(o.Id)).ToArray();
        return children.Concat(children.SelectMany(child => GetAllChildren(app, child)));
  2. Load the computation cache.

    This step consists of executing the GetLayout method for all the objects collected in step 1. The preferred way to do this is to issue all GetLayout calls concurrently.

    This takes advantage of engines capability of performing computations in parallel.

    var allLayoutTasks = allObjects.Select(o => o.GetLayoutAsync());