Performance
How to keep a script fast, so the chart stays smooth.
Scripts run in the chart's main thread and share its frame. A slow draw makes the whole chart stutter. The indicator list shows each script's handler and draw time (mean over the last second): check it while you work.
Handlers compute, draw emits
- Do per-event work in handlers, once: sums, profiles, parsing, lookups. Store the results in state.
drawruns on every pan, zoom and crosshair move. It should only position and emit shapes.- Many events in one frame cost one
draw: handlers do not redraw on their own.
More: State and draw.
Draw only what is in view
- Skip items outside
frame.visibleTimebefore callingtimeToX. - For sorted data, binary search the first visible item instead of scanning from 0:
/** First index with `time >= target`. */
function lowerBound(list: readonly { readonly time: number }[], target: number): number {
let low = 0;
let high = list.length;
while (low < high) {
const mid = (low + high) >> 1;
if (list[mid]!.time < target) low = mid + 1;
else high = mid;
}
return low;
}
for (let i = lowerBound(points, frame.visibleTime.from); i < points.length; i += 1) {
if (points[i]!.time > frame.visibleTime.to) break;
// …
}- Hide details that are too small to see, e.g. text below a few px: the footprint switches from numbers to bars when rows get small.
Batch shapes
- One
g.polylinewith all points is far cheaper than oneg.lineper segment. g.polygonfills any outline in one call, e.g. a band between two lines.g.textis the most expensive call. Keep it to what is readable.
Textures for grids
A heatmap of thousands of cells as rects is slow. g.texture draws a whole grid as one GPU quad:
- Create the grid once:
ctx.createGrid(columns, rows)returns aResult, checkisErr(). - Write columns in the handler (
setColumn,pushColumn). Only changed columns upload. - Draw it in
drawwith aColorMap.NaNcells are transparent.
See Liquidity heatmap and the Graphics reference.
Cache per view
Results needed only for what is visible, e.g. a profile per session, can be built lazily in draw and cached in state with a version. Rebuild one only when its data changed. See TPO and State and draw.
Streams
trades({ minSize })drops small trades at the source, before they reach your handler.- Ask only for the history you need:
warmup,history. sessionOfis slow (time zones): call it once per session, not per bar.