Controlling Table Update Frequency
There are two underlying processes used when updating tables with live data in Deephaven.
- 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.
- 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
orminimumInterCycleSleep
(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