This file is generated by tests/perf/test_readme_timings.py. The benchmark first writes docs/timings.tsv, then renders this Markdown page and timing plots from that TSV.

Example timings from the opt-in performance benchmark, measured in release mode on one development machine. Treat them as indicative, not as a portability, stability, or universality guarantee.

Benchmark environment

Field Value
Recorded 2026-05-24 17:00 UTC
Runtime Python 3.12.13, RDKit 2026.03.1
Platform Linux-6.17.0-23-generic-x86_64-with-glibc2.36
CPU AMD Ryzen 5 7640U w/ Radeon 760M Graphics; 12 logical CPUs visible
Memory limit 2 GiB
Container compose/perf.yml perf service, network disabled
  • This is a small curated benchmark: 9 molecules, 2 writer modes, and 7 timing repeats per row.
  • This is not a workload study and not an exact-versus-exact comparison.
  • Support: the size of the exact rooted SMILES support across all root atoms.
  • Grimace enum (per-root union): union of MolToSmilesEnum(..., rootedAtAtom=root_idx, canonical=False, doRandom=True, isomericSmiles=<table mode>) over every root atom.
  • The direct public MolToSmilesEnum(..., rootedAtAtom=-1, ...) path is not timed in this column and can differ materially from the explicit per-root union shown here.
  • Decoder enum (branch-preserving, per-root): exhaustive traversal of MolToSmilesDecoder(..., rootedAtAtom=root_idx, canonical=False, doRandom=True, isomericSmiles=<table mode>).next_choices over every root atom, then unioned.
  • Decoder enum (determinized, per-root): the same per-root traversal, using MolToSmilesDeterminizedDecoder(...).
  • Decoder enum (branch-preserving, merged): exhaustive traversal of MolToSmilesDecoder(..., rootedAtAtom=-1, canonical=False, doRandom=True, isomericSmiles=<table mode>).next_choices.
  • Decoder enum (determinized, merged): the same merged traversal, using MolToSmilesDeterminizedDecoder(...).
  • RDKit to 1/2 support: repeated RDKit MolToSmiles(..., canonical=False, doRandom=True, rootedAtAtom=root_idx, isomericSmiles=<table mode>) draws across all roots until half of the exact support has been seen.
  • RDKit to full support: the same sampling process until the full exact support has been seen.
  • Non-stereo means isomericSmiles=False.
  • Stereo means isomericSmiles=True.
  • All timing columns are shown as time mean ± std.
  • The two RDKit columns also show (draw mean ± std) over repeated seeded trials.
  • The published table does not directly rank every public exact path: it times Grimace enum (per-root union) rather than the direct public MolToSmilesEnum(..., rootedAtAtom=-1) path, and some merged decoder rows are numerically lower than that per-root union column.
  • The merged decoder rows expose the public all-roots decoder path directly, so they can diverge substantially from the explicit per-root rows.
  • Read the RDKit comparison as ‘faster on this benchmark against this sampling baseline’, not as a general claim about every molecule or every SMILES-writing workload.
  • The determinized decoder can reduce exhaustive decoder cost on some molecules, but direct exact enumeration is still faster on these cases.

Non-stereo (isomericSmiles=False)

Molecule Atoms Support Grimace enum (per-root union) Decoder enum (branch-preserving, per-root) Decoder enum (determinized, per-root) Decoder enum (branch-preserving, merged) Decoder enum (determinized, merged) RDKit to 1/2 support RDKit to full support
CC(=O)Oc1ccccc1C(=O)O 13 304 10.1 ± 0.2 ms 20.1 ± 1.8 ms 19.4 ± 0.5 ms 9.5 ± 0.6 ms 10.2 ± 0.5 ms 5.7 ± 0.3 ms (229.6 ± 9.6 draws) 69.5 ± 12.5 ms (3106.4 ± 402.2 draws)
C1CC2(CCO1)CO2 8 36 4.4 ± 0.0 ms 5.8 ± 0.2 ms 6.0 ± 0.3 ms 2.2 ± 0.0 ms 1.5 ± 0.0 ms 0.4 ± 0.1 ms (24.3 ± 3.6 draws) 2.2 ± 0.6 ms (156.7 ± 46.0 draws)
CN1CCC[C@H]1c1cccnc1 12 136 8.6 ± 0.1 ms 13.1 ± 0.7 ms 12.9 ± 0.3 ms 4.4 ± 0.0 ms 4.4 ± 0.2 ms 2.4 ± 0.4 ms (97.3 ± 5.4 draws) 18.5 ± 3.5 ms (861.1 ± 154.4 draws)
CNC(=O)O/N=C(\C)SC 10 72 5.3 ± 0.1 ms 7.1 ± 0.1 ms 7.4 ± 0.6 ms 2.3 ± 0.0 ms 2.3 ± 0.0 ms 0.7 ± 0.1 ms (48.9 ± 4.2 draws) 6.5 ± 1.5 ms (454.6 ± 98.3 draws)
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O 14 688 12.4 ± 0.2 ms 34.0 ± 2.3 ms 32.5 ± 2.0 ms 18.4 ± 0.2 ms 18.0 ± 0.2 ms 11.5 ± 0.4 ms (514.6 ± 16.5 draws) 183.2 ± 13.6 ms (8108.6 ± 547.3 draws)
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1 17 1504 21.0 ± 0.6 ms 108.9 ± 30.5 ms 67.3 ± 2.1 ms 44.2 ± 1.1 ms 43.6 ± 0.4 ms 31.1 ± 0.7 ms (1162.3 ± 18.4 draws) 577.4 ± 108.5 ms (20970.1 ± 4191.5 draws)
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-] 16 620 17.5 ± 0.2 ms 54.6 ± 1.6 ms 55.2 ± 1.9 ms 36.0 ± 1.3 ms 22.3 ± 0.2 ms 10.9 ± 0.3 ms (485.9 ± 13.7 draws) 184.2 ± 46.4 ms (8272.0 ± 2122.3 draws)
C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12 22 5548 44.1 ± 0.3 ms 256.5 ± 5.1 ms 250.8 ± 4.6 ms 185.5 ± 7.8 ms 194.2 ± 12.9 ms 169.6 ± 3.1 ms (4707.6 ± 69.3 draws) 4762.3 ± 674.4 ms (129595.7 ± 17892.8 draws)
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1 25 12096 92.5 ± 5.9 ms 1104.4 ± 40.5 ms 719.6 ± 13.3 ms 702.5 ± 13.6 ms 512.7 ± 136.0 ms 419.9 ± 10.1 ms (9541.7 ± 102.1 draws) 13243.8 ± 3191.7 ms (311150.0 ± 67407.2 draws)
CC(=O)Oc1ccccc1C(=O)O:
Timing bar chart for CC(=O)Oc1ccccc1C(=O)O
C1CC2(CCO1)CO2:
Timing bar chart for C1CC2(CCO1)CO2
CN1CCC[C@H]1c1cccnc1:
Timing bar chart for CN1CCC[C@H]1c1cccnc1
CNC(=O)O/N=C(\C)SC:
Timing bar chart for CNC(=O)O/N=C(\C)SC
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O:
Timing bar chart for N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1:
Timing bar chart for COc1ccc2cc([C@H](C)C(=O)O)ccc2c1
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-]:
Timing bar chart for O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-]
C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12:
Timing bar chart for C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1:
Timing bar chart for CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1

Stereo (isomericSmiles=True)

Molecule Atoms Support Grimace enum (per-root union) Decoder enum (branch-preserving, per-root) Decoder enum (determinized, per-root) Decoder enum (branch-preserving, merged) Decoder enum (determinized, merged) RDKit to 1/2 support RDKit to full support
CC(=O)Oc1ccccc1C(=O)O 13 304 13.3 ± 0.1 ms 24.2 ± 1.4 ms 22.2 ± 0.1 ms 11.3 ± 0.1 ms 10.4 ± 0.3 ms 4.6 ± 0.1 ms (217.9 ± 5.3 draws) 55.1 ± 13.5 ms (2466.9 ± 539.3 draws)
C1CC2(CCO1)CO2 8 36 6.1 ± 0.1 ms 8.6 ± 0.5 ms 7.9 ± 0.3 ms 3.2 ± 0.0 ms 2.5 ± 0.0 ms 0.3 ± 0.1 ms (22.7 ± 2.6 draws) 2.5 ± 0.6 ms (178.0 ± 40.0 draws)
CN1CCC[C@H]1c1cccnc1 12 136 12.4 ± 1.0 ms 17.3 ± 0.4 ms 16.8 ± 0.4 ms 6.3 ± 0.0 ms 5.9 ± 0.1 ms 2.0 ± 0.1 ms (93.1 ± 6.3 draws) 18.5 ± 5.7 ms (877.9 ± 271.1 draws)
CNC(=O)O/N=C(\C)SC 10 72 18.9 ± 1.6 ms 29.2 ± 6.0 ms 22.0 ± 1.2 ms 14.8 ± 1.0 ms 14.1 ± 0.6 ms 0.8 ± 0.1 ms (50.1 ± 6.7 draws) 6.8 ± 1.6 ms (416.4 ± 96.6 draws)
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O 14 688 18.8 ± 0.4 ms 41.9 ± 3.5 ms 37.7 ± 2.5 ms 26.0 ± 1.1 ms 23.6 ± 1.8 ms 13.1 ± 1.1 ms (521.1 ± 22.0 draws) 203.7 ± 69.8 ms (8194.6 ± 2525.9 draws)
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1 17 1504 34.5 ± 6.2 ms 127.6 ± 33.9 ms 87.9 ± 2.4 ms 69.3 ± 11.5 ms 55.8 ± 3.3 ms 32.4 ± 1.9 ms (1139.4 ± 30.2 draws) 568.0 ± 120.6 ms (19420.1 ± 3609.7 draws)
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-] 16 1240 24.6 ± 1.1 ms 73.9 ± 3.9 ms 76.8 ± 8.1 ms 49.2 ± 2.8 ms 44.5 ± 4.7 ms 25.7 ± 0.5 ms (984.4 ± 18.8 draws) 444.9 ± 44.7 ms (16631.3 ± 1082.0 draws)
C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12 22 5548 181.9 ± 3.1 ms 2108.9 ± 164.0 ms 2583.7 ± 540.0 ms 1987.2 ± 393.5 ms 2156.6 ± 281.4 ms 204.3 ± 11.6 ms (4702.4 ± 31.1 draws) 4955.7 ± 632.4 ms (126625.9 ± 18285.0 draws)
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1 25 12096 400.6 ± 22.7 ms 6122.5 ± 200.2 ms 4966.7 ± 143.8 ms 5527.7 ± 301.5 ms 4496.1 ± 67.6 ms 404.5 ± 49.5 ms (9556.3 ± 55.7 draws) 10864.7 ± 1345.5 ms (260894.1 ± 28940.6 draws)
CC(=O)Oc1ccccc1C(=O)O:
Timing bar chart for CC(=O)Oc1ccccc1C(=O)O
C1CC2(CCO1)CO2:
Timing bar chart for C1CC2(CCO1)CO2
CN1CCC[C@H]1c1cccnc1:
Timing bar chart for CN1CCC[C@H]1c1cccnc1
CNC(=O)O/N=C(\C)SC:
Timing bar chart for CNC(=O)O/N=C(\C)SC
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O:
Timing bar chart for N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1:
Timing bar chart for COc1ccc2cc([C@H](C)C(=O)O)ccc2c1
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-]:
Timing bar chart for O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-]
C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12:
Timing bar chart for C=C1CC[C@H](O)C/C1=C/C=C1\CCC[C@]2(C)[C@@H]([CH]C)CC[C@@H]12
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1:
Timing bar chart for CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1