# How to Optimize ECharts Performance for Large Datasets: A Complete Guide to Large-Mode Rendering

> Boost ECharts performance with large-mode rendering. Learn to optimize for large datasets by setting large: true or adjusting largeThreshold for faster graphics and reduced memory. Improve your ECharts experience today.

- Repository: [The Apache Software Foundation/echarts](https://github.com/apache/echarts)
- Tags: performance
- Published: 2026-03-04

---

**Enable ECharts large-mode by setting `large: true` or adjusting `largeThreshold` to switch from individual graphic elements to typed-array rendering, reducing memory usage and draw calls for datasets exceeding 2,000 points.**

When visualizing massive datasets in the `apache/echarts` repository, the default rendering path creates individual graphic elements for every data point, causing memory pressure and frame drops. To optimize ECharts performance, the library implements an internal **large-mode** pipeline that uses typed arrays and batched draw calls instead of DOM-heavy graphic primitives.

## Understanding ECharts Large-Mode Architecture

The large-mode mechanism relies on three core components working together during the rendering lifecycle.

### The Scheduler and Pipeline Context

The `Scheduler` class in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts) (lines 60‑63) maintains a `PipelineContext` that tracks whether the current frame should use large-mode rendering. This context holds two critical boolean flags:

- `large`: Indicates whether the series should use typed-array rendering.
- `progressiveRender`: Controls whether data should be painted in chunks to maintain UI responsiveness.

The scheduler evaluates data length against series-specific thresholds to set these flags before the render cycle begins.

### Render Planner and Series Models

The `createRenderPlanner` function in [`src/chart/helper/createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/src/chart/helper/createRenderPlanner.ts) (lines 43‑48) acts as a stage handler that reads the `pipelineContext.large` flag and applies it to the series model. When the flag changes between render cycles—such as when a dataset grows from 1,000 to 50,000 points—the planner returns `'reset'`, triggering a complete rebuild of the series layout and switching the rendering path from standard to large-mode.

Series models expose the configuration interface for this behavior:

- **`ScatterSeries`** ([`src/chart/scatter/ScatterSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/scatter/ScatterSeries.ts), lines 137‑140): Defaults to `large: false` with `largeThreshold: 2000`.
- **`BarSeries`** ([`src/chart/bar/BarSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/BarSeries.ts), lines 14‑20, 24‑31): Implements `getProgressive()` and `getProgressiveThreshold()` methods that adapt progressive settings when large mode activates.
- **`BaseBarSeries`** ([`src/chart/bar/BaseBarSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/BaseBarSeries.ts), line 204): Sets the default `large` flag to `false`.
- **`LinesSeries`** ([`src/chart/lines/LinesSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/lines/LinesSeries.ts), line 410): Provides similar large-mode defaults for line-type visualizations.

## How Large-Mode Rendering Works Internally

The transition from standard to large-mode involves five distinct stages that optimize memory layout and rendering throughput.

### Threshold Detection and Pipeline Flags

During the update cycle, the scheduler compares the current data length against the series `largeThreshold`. For scatter series, the default threshold is 2000 points; for bar series, it is 400. The detection logic in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts) (around line 230) evaluates:

```typescript
const large = this.option.large ? true
             : dataLen >= this.get('largeThreshold');

```

When this condition evaluates to `true`, the `pipelineContext.large` flag is set, signaling downstream components to use the optimized rendering path.

### Typed-Array Layout and Memory Optimization

Once large-mode activates, the series stops creating individual ZRender graphic elements (which consume significant memory for DOM references and styling properties). Instead, it allocates compact typed arrays:

- `largePoints`: A `Float32Array` storing x/y coordinates.
- `largeBackgroundPoints`: Optional buffer for background geometries.
- `largeDataIndices`: An index mapping for interaction and tooltip lookups.

These buffers are processed by the renderer in a single draw call, bypassing the expensive per-element creation and update cycles of the standard path. This reduces memory usage from megabytes to kilobytes per thousand points and eliminates thousands of individual draw calls.

### Progressive Rendering for Massive Data

For datasets exceeding 100,000 points, even typed-array rendering can cause frame drops during the initial paint. The `progressive` option enables chunked rendering:

```typescript
// From BarSeries.ts lines 14-20
getProgressive(): number | false {
    return this.get('large') ? (this.get('progressive') || 5000) : false;
}

```

The series returns a progressive step size (default 5000 for large mode) and a threshold (`getProgressiveThreshold()`) that is automatically enlarged to at least the `largeThreshold`. The scheduler uses these values to paint data in batches across multiple animation frames, keeping the UI responsive while the chart initializes.

### Reset on Mode Change

If a dataset dynamically grows or shrinks across the threshold boundary, the render planner detects the flag change and returns `'reset'` ([`createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/createRenderPlanner.ts) lines 46‑48). This triggers a complete series layout rebuild, ensuring the correct rendering path is used without visual artifacts or memory leaks from mixed-mode rendering.

## Practical Configuration: Optimize ECharts Performance with Code Examples

### Enabling Large-Mode for Scatter Plots

The scatter series provides the most dramatic performance improvements with large-mode due to the high point count typical in scatter visualizations.

```javascript
const chart = echarts.init(document.getElementById('chart'));

// Generate 50,000 random data points
const data = Array.from({length: 50000}, () => [
  Math.random() * 100,
  Math.random() * 100
]);

const option = {
  xAxis: {},
  yAxis: {},
  series: [{
    type: 'scatter',
    // Force large-mode regardless of data size
    large: true,
    // Only switch to large-mode when exceeding 10,000 points
    largeThreshold: 10000,
    // Render in batches of 5,000 points per frame
    progressive: 5000,
    data: data
  }]
};

chart.setOption(option);

```

**Key configuration points:**
- **`large: true`** forces typed-array rendering even for smaller datasets, useful when you anticipate dynamic growth.
- **`largeThreshold: 10000`** overrides the default 2000-point threshold for scatter series as defined in [`src/chart/scatter/ScatterSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/scatter/ScatterSeries.ts).
- **`progressive: 5000`** ensures the UI remains responsive during the initial render of 50,000 points.

### Configuring Progressive Rendering for Bar Charts

Bar charts use a lower default threshold (400 bars) for large-mode activation and adapt progressive settings automatically.

```javascript
const option = {
  xAxis: {
    type: 'category',
    data: Array.from({length: 20000}, (_, i) => `Item ${i}`)
  },
  yAxis: {},
  series: [{
    type: 'bar',
    // Auto-detect large mode (default largeThreshold = 400)
    // Set higher threshold so large-mode triggers only above 5,000 bars
    largeThreshold: 5000,
    // Chunk size for progressive painting
    progressive: 2000,
    data: Array.from({length: 20000}, () => Math.round(Math.random() * 1000))
  }]
};

echarts.init(document.getElementById('chart')).setOption(option);

```

**Implementation details from the source:**
According to [`src/chart/bar/BarSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/BarSeries.ts) (lines 14‑20), the `getProgressive()` method returns `this.get('large') ? (this.get('progressive') || 5000) : false`. This means when `large` mode activates (either manually or via `largeThreshold`), the series automatically adopts progressive rendering with a default chunk size of 5000 unless overridden.

### Dynamic Mode Switching After Data Updates

When datasets grow dynamically across the threshold boundary, ECharts automatically rebuilds the rendering pipeline.

```javascript
// Initial small dataset within normal rendering limits
let data = Array.from({length: 1500}, () => [
  Math.random() * 100, 
  Math.random() * 100
]);

chart.setOption({
  series: [{
    type: 'scatter', 
    data, 
    largeThreshold: 2000
  }]
});

// Simulate data growth beyond threshold
setTimeout(() => {
  data = Array.from({length: 80000}, () => [
    Math.random() * 100, 
    Math.random() * 100
  ]);
  
  chart.setOption({
    series: [{
      type: 'scatter', 
      data
      // large will be auto-enabled (dataLen > largeThreshold)
    }]
  });
}, 3000);

```

**Automatic pipeline reset:**
As implemented in [`src/chart/helper/createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/src/chart/helper/createRenderPlanner.ts) (lines 46‑48), when the `pipelineContext.large` flag changes between `true` and `false`, the planner returns `'reset'`. This triggers a complete series layout rebuild, ensuring the series switches from standard graphic element rendering to the typed-array `largePoints` buffer without visual artifacts.

## Performance Tuning Best Practices

To maximize rendering speed when working with massive datasets in ECharts, apply these configuration strategies derived from the source code implementation:

- **Force large-mode explicitly** with `large: true` when you know datasets will exceed 10,000 points. This bypasses threshold detection and immediately allocates `Float32Array` buffers in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts), preventing the memory spike of initial standard rendering.

- **Raise the switching threshold** using `largeThreshold` when you need interactive features like individual point emphasis or labels for moderately large datasets (5,000–10,000 points). The default 2000 for scatter ([`src/chart/scatter/ScatterSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/scatter/ScatterSeries.ts)) may be conservative for modern hardware.

- **Combine large-mode with progressive rendering** by setting both `large: true` and `progressive: 5000`. As defined in [`src/chart/bar/BarSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/BarSeries.ts), the series automatically enlarges progressive thresholds when large mode is active, painting data in chunks to maintain 60fps during initialization.

- **Disable expensive visual effects** including `animation`, `label`, and `emphasis.scale` when using large-mode. While the typed-array path in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts) reduces memory overhead, per-point effects still require individual processing that defeats the optimization purpose.

- **Monitor pipeline resets** when dynamically updating data across threshold boundaries. The [`createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/createRenderPlanner.ts) logic triggers a full series reset when switching modes, which may cause a brief frame drop; batch updates to stay consistently above or below `largeThreshold`.

## Summary

Optimizing ECharts performance for large datasets requires understanding the library's internal **large-mode** pipeline that switches from individual graphic elements to typed-array rendering. Key takeaways include:

- **Threshold-based activation**: Series automatically switch to large-mode when data exceeds `largeThreshold` (default 2000 for scatter, 400 for bar), controlled by the `Scheduler` in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts).
- **Memory efficiency**: Large-mode stores coordinates in `Float32Array` buffers (`largePoints`, `largeDataIndices`) rather than full ZRender elements, reducing memory usage by orders of magnitude.
- **Progressive rendering**: The `progressive` option chunks rendering across frames when combined with large-mode, preventing UI freezing during initial paint of 100,000+ points.
- **Dynamic adaptation**: When datasets grow across threshold boundaries, [`createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/createRenderPlanner.ts) automatically triggers a series reset to rebuild the typed-array layout without manual intervention.

## Frequently Asked Questions

### What is the default threshold for activating large-mode in ECharts scatter plots?

The default `largeThreshold` for scatter series is **2000 points**, as defined in [`src/chart/scatter/ScatterSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/scatter/ScatterSeries.ts) (lines 137‑140). When your dataset exceeds this count and `large` is not explicitly set to `false`, ECharts automatically switches to typed-array rendering to maintain performance.

### How does large-mode reduce memory usage compared to standard rendering?

Standard rendering creates individual ZRender graphic elements for every data point, each carrying DOM references, style properties, and event handlers. In large-mode, ECharts stores data in compact **typed arrays** (`Float32Array` for coordinates, `Uint32Array` for indices) as implemented in [`src/core/Scheduler.ts`](https://github.com/apache/echarts/blob/main/src/core/Scheduler.ts). This reduces per-point memory overhead from hundreds of bytes to approximately 8 bytes per coordinate pair.

### Can I use progressive rendering without enabling large-mode?

Yes, but with limitations. The `progressive` option works independently, but as implemented in [`src/chart/bar/BarSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/BarSeries.ts) (lines 14‑20), the `getProgressive()` method returns `false` when `large` is disabled unless you explicitly set a `progressive` value in your options. For optimal performance with datasets exceeding 50,000 points, combining both features is recommended.

### Why does my chart flicker or reset when updating data across the large-mode threshold?

This occurs because [`src/chart/helper/createRenderPlanner.ts`](https://github.com/apache/echarts/blob/main/src/chart/helper/createRenderPlanner.ts) (lines 46‑48) detects when the `pipelineContext.large` flag changes between `true` and `false`. To prevent mixed-mode rendering artifacts, the planner returns `'reset'`, forcing the series to rebuild its internal layout and switch from standard graphic elements to typed-array buffers (or vice versa). To minimize disruption, keep `largeThreshold` consistent or explicitly set `large: true` to avoid automatic threshold crossing.