Measure the performance of Ruby tree/hierarchy gems. Find what's slow, prove what's fast, and give maintainers evidence for making changes.
Primarily benchmarks ancestry with closure_tree for cross-library comparison.
- Built a benchmark suite covering read operations, write operations, format comparisons, and version-over-version tracking.
- Tested
ancestryconfigurations (mp1,mp2,mp3,ltree,array) with options likecache_depth,parent, and virtual columns. - Compared against
closure_treeto expose blind spots that only show up when you look at a different architecture. - Trees are tested with
600-6,000at2-50nodes deep. - Note: most real-world hierarchies are broad and shallow
- biological taxonomies go ~
9levels deep - large org charts rarely exceed
12.
- biological taxonomies go ~
Both gems are Ruby libraries generating SQL. A technique one uses can often be adopted by the other. Comparing across gems is how you tell "this approach is fundamentally slower" from "this implementation has a fixable inefficiency."
- Comparing with
closure_treeexposed thatancestryhad a387xgap onparent. closure_treedoesarrangebetter and pulls ahead at very large scales.closure_treecachesparent_idfrom the hierarchy. This can be done withancestryas well.- I had expected
closure_treeto perform better with deep hierarchies, but the extra nodes slowed it down.
Wrote up a more details description of our findings.md
See the results page for benchmarks, charts, and a glossary of configurations.
- Ordered descendants -- where
closure_tree's hierarchy table ordering should shine - Write cost comparison --
ancestryupdates one column,closure_treemaintains a hierarchy table - Add more alternatives
awesome_nested_set-- nested set pattern (lft/rgtcolumns)acts_as_recursive_tree--parent_idwithWITH RECURSIVEacts_as_sane_tree--parent_idwithWITH RECURSIVE
Requires local checkouts of ancestry and benchmark-sweet as sibling directories.
bundle install
# compare ancestry configurations
DB=pg bundle exec ruby read_bench.rb --all
DB=pg bundle exec ruby write_bench.rb --all
# compare ancestry versions (requires ancestry git worktrees)
DB=pg bundle exec ruby read_bench.rb -v v5.0.0
DB=pg bundle exec ruby read_bench.rb -v master
# compare libraries
DB=pg bundle exec ruby compare_bench.rb
# generate HTML charts and tables
bundle exec ruby gen_html.rb