I wrote ngx-lanes, so take this with the right amount of salt: I'm not a neutral party. That's why everything below is reproducible with three commands, and why I've tried hard to give the other two libraries a fair setup.

The question: how do Angular timeline libraries cope with 1,000 resources and 10,000 bars? That's a realistic size for planning screens: a fleet over two months, a hospital rota, a factory floor.

The contenders

  • ngx-lanes 0.1.1: my resource timeline. Rows are resources, bars are assignments.
  • @worktile/gantt 22.0.0 (ngx-gantt): the most established open-source Angular Gantt.
  • schedula-core-angular 1.4.0: the official Angular wrapper of SchedulaCore, a resource-based Gantt.

The setup

  • The same 10,000 bars for all three, generated with a fixed seed.
  • The same density: about 8 days per screen.
  • Each library configured the way its docs recommend. For ngx-gantt that means virtualScrollEnabled and NgxGanttModule; for schedula-core, animations off.
  • A production build with Angular 22, headless Chrome, a 1400 × 850 viewport, median of 3 runs.
  • CPU throttled 4× in Chrome to approximate a modest laptop. A fast machine hides problems your users will see.

I measured four things: time until the first bar is painted, DOM nodes after that, frame times while scrolling with the mouse wheel, and how long the main thread is blocked during the scroll.

Results (CPU throttled 4×)

Library Load DOM nodes Frame p95 Slow frames Main thread blocked while scrolling
ngx-lanes 0.46 s 344 16.8 ms 0% 0 s
ngx-gantt 1.07 s 417 49.9 ms 6.6% 1.4 s
schedula-core 66 s 186,721 1,100 ms 100% 159 s

Without throttling, ngx-lanes and ngx-gantt both scroll at a perfect 60 fps; the difference is load time (0.15 s against 0.30 s). schedula-core still takes 14 s to show the plan.

What explains the gap

schedula-core renders everything. All 10,000 bars and their decorations are in the DOM from the start: 186,721 elements. Every scroll then has to move all of them. It's a fine design for a few hundred bars; at this size it collapses.

ngx-gantt virtualizes rows, but it's a task Gantt. It shows one bar per row, so 10,000 bars become 10,000 rows under 1,000 resource headers. Its virtualization keeps the DOM small, yet a screen shows about 35 bars where ngx-lanes shows about 110. Even rendering a third of the bars, it blocks the main thread for 1.4 s across the scroll.

ngx-lanes virtualizes in both directions. It only renders rows within the viewport (plus a margin of four), and within those rows only bars within 300 px of the visible time range. Finding those bars is a binary search per resource, not a scan. The size of the DOM depends on what's on screen, not on how many bars the plan has. I explained the technique in my previous post.

Where the others win

Speed isn't everything, and ngx-lanes is new. Today:

  • ngx-gantt has dependency links, drag and drop, a tree table, baselines and years of production use. If you need a project Gantt with those features, it's a solid choice.
  • schedula-core ships themes, a built-in editing popup and, in its paid version, drag and drop, calendars and context menus.
  • ngx-lanes is a read-only timeline for now. Drag and drop, conflict detection and live updates are on my roadmap.

Reproduce it

Everything is in the repo: the app, the runner script and the raw results.

git clone https://github.com/dmartinezzm/ngx-lanes cd ngx-lanes/benchmarks npm install && npm run build npm run bench -- --runs 3 --chrome "/path/to/chrome" 

One practical note: schedula-core-angular 1.4.0 is published without entry points in its package.json, so Angular can't import it as is. The benchmark adds them with a small script that points at the package's own build output.

If you think a library is misconfigured, open an issue or a pull request and I'll rerun the numbers. And if you build planning screens in Angular, I'd love to hear which of these limits you've hit.