Benchmarks

A site of 30,000 pages in 24 languages, built by Maptain and by sitemap_generator on the same machine: about 400 times faster when a few records changed, 15 times for a full build.

Building 720,000 URLs

bench/build.rb creates 30,000 records, builds their sitemap in 24 languages, builds it again with nothing new, then once more after three records changed. Every URL carries the 25 hreflang links of its page. It then builds the same sitemap, URLs, dates and links, with sitemap_generator, which has no build that skips what did not change.

Ruby 4.0.9 without YJIT, Rails 8.1.4, sitemap_generator 7.1.1, SQLite in memory, Apple M5 Max, median of 3 runs
BuildMaptainsitemap_generatorFasterFiles written
Nothing new0.004 s150 s(nothing to write)0
3 records changed0.35 s150 s430×2
Everything, 720,000 URLs9.9 s150 s15×55 (16.5 MiB gzipped)

With YJIT, the same runs give 0.012 s, 0.32 s and 9.5 s for Maptain, and 115 s for sitemap_generator: 360 and 12 times faster instead of 430 and 15.

Seconds depend on the machine: the full build took 32 s on a Linux x86_64 server with Ruby 3.3.6, before the change to gzip, three times as long as here. Compare builds on the same machine rather than with this table: the ratios hold, the seconds do not.

The URLs here are built from a string: with route helpers and a real database, every build takes longer, and the gap narrows a little. On a copy of a production app's database, 560,000 URLs built on a laptop before the change to gzip, Maptain's full build took 35 s where sitemap_generator took 468 s, 13 times faster, and a build with three changed products 2.8 s, 170 times faster.

Why the full build takes seconds

sitemap_generator lists every URL again at each run, so each of its builds is a full one. Maptain asks the database one question per source, and rewrites only the files whose records moved: that is the build a site runs every day, or after every deploy.

The full build runs once a week (rebuild_every), to catch what the database numbers cannot see. Its size grows with the square of the languages: each of the 720,000 URLs lists the 25 links of its page, about 18 million links and 2 GiB of XML before compression. Maptain writes that XML as strings, without a document tree, and spends most of the time in gzip, at its best level: files that search engines download again and again are worth a few more seconds once a week. The largest file is 39.8 MiB before compression, under the 50 MiB the protocol allows.

Running it again

From a checkout of the gem, once with YJIT off and once with it on:

bundle exec ruby bench/build.rb
bundle exec ruby --yjit bench/build.rb

It takes a few minutes, nearly all of them in sitemap_generator.