Controlling Table Update Frequency

There are two underlying processes used when updating tables with live data in Deephaven. 

  1. When new data is generated on the server, the Live Table Monitor (LTM) first manages the process of updating the source tables and the derived tables with the new data. At this point, data updates are available within the server process.
  2. Once a table has been updated during the LTM refresh cycle, the Viewport Update process sends the new data to the console where rows are added to the table(s) that are presented in the user interface.

These processes are illustrated below.

Live Table Monitor

The Live Table Monitor ultimately controls how often data is refreshed on the server. If the source table is updated with new data, then all the derived tables for that source table (if any)  are incrementally updated. This includes when one of the derived tables is also the source table for subsequently derived tables. Then the next source table is updated as well as its derived tables (if any). The refresh cycle is completed after the last set of source and derived tables are updated.  An illustration of the overall process follows:

The Live Table Monitor has five user-configurable properties:

  • LiveTableMonitor.targetCycleTime
  • LiveTableMonitor.intraCycleSleep
  • LiveTableMonitor.minimumInterCycleSleep
  • LiveTableMonitor.intraCycleYield
  • LiveTableMonitor.interCycleYield
  • LiveTableMonitor.updateThreads

Each property is described below.

targetCycleTime

The targetCycleTime property sets the target time (in milliseconds) for one Live Table Monitor refresh cycle to complete. This includes updating each source table and the corresponding derived tables. The syntax follows:

LiveTableMonitor.targetCycleTime=<milliseconds>

For example, when the targetCycleTime is set to 500, the query engine attempts to complete the entire refresh cycle in 500 milliseconds. 

The value set for this property does not guarantee the actual time for the cycle to complete. If the actual refresh cycle completes faster than the value set for targetCycleTime, the next refresh cycle is paused until the value has been reached.  If the actual refresh cycle takes longer than the value set for targetCycleTime, the refresh cycle will start again as soon as possible after the cycle completes. 

A variety of conditions can cause the actual refresh cycle to take longer than the targetCycleTime:

  • The actual time needed for incremental update processing from refreshed tables may be longer than anticipated.
  • The Live Table Monitor refresh thread may contend on the LiveTableMonitor lock, which prevents data refresh during the middle of an operation. For example, if two threads are changing the same data at the same time, placing a lock on the data prevents another thread from changing that data until the lock is once again available. This is especially important for the Live Table Monitor.
  • If the server is busy, the refresh thread may not be scheduled.
  • Configuration settings such as the intraCycleSleep or minimumInterCycleSleep (see below) may cause the cycle to be longer than the target.

intraCycleSleep

The intraCycleSleep property sets the minimum length of time (in milliseconds) to wait between the update of one set of tables (both source and derived) and the next set of tables (if any) within the same cycle. The syntax follows:

LiveTableMonitor.intraCycleSleep=<milliseconds>

For example, if intraCycleSleep is set to 100, the Live Table Monitor will enforce a 100 millisecond waiting period between each set of tables (both source and derived) being refreshed in a given cycle.

minimumInterCycleSleep

The minimumInterCycleSleep property sets the minimum length of time (in milliseconds) to wait before starting another refresh cycle after the previous cycle has completed. The syntax follows:

LiveTableMonitor.minimumInterCycleSleep=<milliseconds>

If the actual cycle time plus the minimumInterCycleSleep value is greater than the targetCycleTime value, the new cycle will begin after the  minimumInterCycleSleep period has elapsed, as shown below.

If the actual cycle time plus the minimumInterCycleSleep value is less than the targetCycleTime value, the new cycle will begin after the  targetCycleTime period has elapsed, as shown below.

For instance, assume a situation where the targetCycleTime is set to 500ms, and the actual time to complete a refresh cycle is 450ms. If the value for minimumInterCycleSleep was set to 0ms (or was not set at all), the Live Table Monitor would start a new refresh cycle once the targetCycleTime value was reached (at 500ms). However, if the  minimumInterCycleSleep was set to 100ms, the Live Table Monitor would wait for 100ms after the end of the actual cycle (450ms) before starting a new refresh cycle. In this case, the new cycle would start at 550ms (actual time plus the value set for minimumInterCycleSleep).

intraCycleYield

The intraCycleYield property is used to set whether the thread should be allowed to yield to the CPU between refreshing tables within a cycle.

When the intraCycleYield property is set to true, the Live Table Monitor process yields to the CPU so it can allow other threads to run, such as filter or sort operations. If the property is set to false, the Live Table Monitor will not yield to the CPU and will immediately begin processing the next source table.  The syntax follows:

LiveTableMonitor.intraCycleYield=<true or false>

Use of this property is designed to prevent the Live Table Monitor refresh thread from starving other threads within the worker, without introducing the latency associated with sleeps.

interCycleYield

Similar to intraCycleYield, the interCycleYield property is used to set whether the thread should be allowed to yield the CPU between refresh cycles.

When the interCycleYield property is set to true, the Live Table Monitor process yields to the CPU between cycles. If the property is set to false, the Live Table Monitor will not yield to the CPU and will immediately proceed to the next cycle.

LiveTableMonitor.interCycleYield=<true or false>

Use of this property is designed to reduce latency while preventing the Live Table Monitor from starving other threads.

updateThreads

The LiveTableMonitor.updateThreads property allows multithreading within the LTM refresh cycle. If a table has multiple derived tables, all the incremental updates will be run in parallel (respecting dependencies) within one loop. The syntax follows, where N is the number of update threads:

LiveTableMonitor.updateThreads=N

For example, table A incrementally updates tables A2 and A3, and table A3 updates A4. When table A is updated, then tables A2 and A3 will update at the same time, followed by table A4. Then, the cycle proceeds to table B. This improves the efficiency of the LTM cycle, allowing the use of more CPU to reduce latency.

To take advantage of multithreading, you may need to restructure your query using the byExternal() method, which divides a single table into multiple derived tables that are defined by key-value pairs in a TableMap. This – in combination with the TableMap.asTable() operation – enables parallelism in the LTM cycle by allowing a TableMap to be operated on as if it were a single table. Then, any table operation will apply to each of the derived tables produced by byExernal() method across multiple threads. Note that merge()must be used at the end of the query to recombine the independent tables into a single table. For example:

t1 = db.i("NS", "TN").where("Date=currentDateNy()")
tables = t1.byExternal("USym")
t2 = tables.asTable().where("Price>150.50").merge()

Live Table Monitor Panel

The Deephaven console includes an optional Live Table Monitor panel that shows performance statistics for query engine code executing within the console (the client). To access this panel, click Advanced and then select Live Table Monitor from the drop-down menu. The overall amount of time used on query engine execution and which operations contributed the most are displayed.

This panel is not visible by default. To enable, add the property IrisConsole.advancedLiveTableMonitorMenuItem and set it to "true."

Viewport Updates

As mentioned earlier, after a table has been updated during the Live Table Monitor refresh, the Viewport Update process sends the new data to the console where rows are added to the table(s) presented in the user interface. The timing for the updates is configurable through the viewport.updateInterval property.  The syntax follows:

viewport.updateInterval=<milliseconds>

The updateInterval property determines how often table data can be sent from the server to the console for display. Each table has an independent viewport update job, which is started immediately after a table is refreshed.  For example, if the updateInterval is set to 1000ms, new data will appear in the console every second, regardless of how often the data refreshes on the server. The lower the value, the more frequently the table can be  updated, assuming there is new data to update and the bandwidth is sufficient. If updates are sent too frequently, they may overwhelm the network. For best performance, the updateInterval should be set so the tables are responsive without updating so frequently they distract the user.


Last Updated: 20 August 2019 09:54 -06:00 UTC    Deephaven v.1.20180917

Deephaven Documentation      Copyright 2016-2018  Deephaven Data Labs, LLC      All Rights Reserved