Benchmarks
Compare Bklit UI against Recharts and TanStack Charts on your own device. Every run uses the same seeded data, size, and chart type. Enter animations are shown for reference but never counted in the scores.This is a basic, informal comparison, not an official benchmark. Results depend on your device and browser, and on how each chart is configured here, so they may not be fully accurate or show any library at its best. Recharts and TanStack Charts are both excellent libraries; see their docs for recommended setups.
Benchmark setup
Same seeded data, same pixel size, one library at a time. Enter animations run but are never scored.
Chart
Points per series
Series
Iterations
Libraries
Live run area
720×320px
Ready to benchmark
Charts mount here one library at a time. Keep this area on screen while the run is in progress.
No results yet
Scores appear here once a run finishes, one card per metric.
Press Run benchmark above. Results come from your device, so run it a few times and compare.
What's being compared
The same chart type and data in each library, so you can check they're comparable.
bklitvworkspace
React + SVG, animated with Motion.
Rechartsv3.10.1
React + SVG, built-in enter animation.
TanStack Chartsv1.1.0
Framework-neutral scene, React SVG host; motion() renderer when animated.
Methodology
What each number means, when timing stops, and how each library was set up.
Every score stops at the first painted frame.
Timings are your device, your browser, right now.
Fairness notes
How each library's chart was configured, and what couldn't be matched exactly.
- bklit
- SVG + Motion. Line, area, bar and scatter all default to a 1100 ms enter reveal; data updates morph paths and tween the y-domain (500 ms).
- Recharts
- SVG. Default enter animation: 1,500 ms for Line/Area, 400 ms for Bar/Scatter. Fixed width/height (no ResponsiveContainer). Line dots disabled to match bklit; hover dot (activeDot) and Tooltip cursor are defaults.
- TanStack Charts
- SVG. The default Chart has no entrance animation; with animation on, the opt-in motion() renderer is used (1,100 ms tween). Hover uses the default linear nearest-point scan (no spatialIndex). Time x uses d3-scale scaleTime; curves via d3Curve(curveMonotoneX).
- Every library draws the same chrome: horizontal grid, x axis, a hover tooltip with a cursor or crosshair, no legend, and a monotone curve for line and area. Each uses its own idiomatic, documented API at a fixed pixel size.
- Animation is on for every scored run, using each library's default. TanStack Charts has no entrance animation by default, so its animated runs use the opt-in motion() renderer. Its numbers therefore reflect that renderer, not the plain default component.
- TanStack's motion() renderer pre-renders a hidden focus ring per point, so its DOM node count is higher than its static renderer would produce.
- TanStack hover uses its default nearest-point lookup, a linear scan. Its large-data guide recommends supplying a spatialIndex for dense charts; we use defaults.
- TanStack grouped bars need one row per category and series, so its adapter reshapes the data. That cost is included in its mount and update times.
- TanStack areas are an areaY plus a decorative lineY edge per series, as its docs recommend, so each series gets a single tooltip row.
- Recharts draws a dot on every line point by default. These are turned off (dot={false}) to match bklit, while the hover dot (activeDot) stays on. Recharts scatter points render as <path> elements.
- Recharts' default enter animation is 1,500 ms for line and area but 400 ms for bar and scatter. Recharts also skips animation when the OS prefers reduced motion, so run with that setting off. Use the animation reference table rather than comparing durations across chart types.
- Hover samples dispatch both pointermove and mousemove, because libraries listen to different events, and time each move to the next painted frame. Tooltip spring or tween motion after that frame is not counted.