This file is generated by scripts/timings_enum_measure.py. The benchmark first writes docs/timings-enum.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-06-06 15:16 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/timings-enum.yml timings-enum 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.
  • In this benchmark, Non-stereo means isomericSmiles=False with the other writer flags at their defaults.
  • Stereo means isomericSmiles=True with the other writer flags at their defaults.
  • 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.
  • Decoder rows measure exhaustive traversal of complete support. They do not measure initialization alone or one selected generation/validation trajectory.
  • 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 12.1 ± 0.8 ms 34.1 ± 2.3 ms 37.4 ± 1.5 ms 20.0 ± 2.0 ms 21.7 ± 0.7 ms 4.5 ± 0.4 ms (230.0 ± 18.8 draws) 61.5 ± 21.3 ms (3086.7 ± 921.8 draws)
C1CC2(CCO1)CO2 8 36 4.1 ± 0.3 ms 11.5 ± 1.2 ms 10.3 ± 0.8 ms 5.3 ± 0.9 ms 3.5 ± 0.5 ms 0.3 ± 0.0 ms (23.0 ± 1.8 draws) 1.9 ± 0.4 ms (155.6 ± 35.8 draws)
CN1CCC[C@H]1c1cccnc1 12 136 8.6 ± 0.8 ms 18.4 ± 1.4 ms 20.0 ± 2.5 ms 9.0 ± 0.4 ms 10.0 ± 0.3 ms 1.9 ± 0.2 ms (97.4 ± 8.7 draws) 18.7 ± 3.2 ms (987.9 ± 169.9 draws)
CNC(=O)O/N=C(\C)SC 10 72 4.8 ± 0.4 ms 9.1 ± 0.9 ms 9.8 ± 0.8 ms 4.2 ± 0.2 ms 4.9 ± 0.2 ms 0.6 ± 0.1 ms (44.1 ± 2.5 draws) 5.9 ± 1.5 ms (483.0 ± 122.3 draws)
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O 14 688 11.7 ± 0.6 ms 53.2 ± 3.9 ms 60.8 ± 2.0 ms 37.8 ± 0.9 ms 44.4 ± 1.4 ms 10.4 ± 0.5 ms (514.3 ± 12.9 draws) 151.4 ± 46.9 ms (7946.7 ± 2448.6 draws)
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1 17 1504 20.8 ± 1.2 ms 136.1 ± 3.8 ms 149.5 ± 5.6 ms 93.9 ± 2.9 ms 110.1 ± 2.3 ms 27.7 ± 1.5 ms (1143.0 ± 34.0 draws) 580.9 ± 114.1 ms (24406.3 ± 4916.2 draws)
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-] 16 620 16.1 ± 0.5 ms 88.9 ± 1.4 ms 107.2 ± 6.3 ms 69.4 ± 1.7 ms 53.6 ± 1.9 ms 9.2 ± 0.3 ms (492.6 ± 14.2 draws) 141.5 ± 37.1 ms (7245.7 ± 2133.7 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 43.7 ± 1.2 ms 500.6 ± 30.5 ms 578.2 ± 30.2 ms 377.0 ± 5.6 ms 453.6 ± 13.1 ms 157.2 ± 6.3 ms (4681.4 ± 66.1 draws) 4108.0 ± 709.0 ms (128516.4 ± 19796.2 draws)
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1 25 12096 82.7 ± 1.0 ms 1987.5 ± 17.0 ms 1575.9 ± 63.3 ms 1479.7 ± 32.6 ms 1062.9 ± 63.2 ms 340.0 ± 3.7 ms (9630.1 ± 75.3 draws) 9282.5 ± 1406.0 ms (261894.6 ± 39129.7 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 12.8 ± 0.7 ms 37.1 ± 2.8 ms 38.6 ± 2.8 ms 21.4 ± 0.7 ms 24.4 ± 1.0 ms 4.2 ± 0.1 ms (222.6 ± 3.8 draws) 61.0 ± 14.4 ms (3128.4 ± 683.9 draws)
C1CC2(CCO1)CO2 8 36 5.7 ± 0.1 ms 10.8 ± 0.4 ms 10.6 ± 1.4 ms 6.5 ± 0.5 ms 5.1 ± 0.6 ms 0.3 ± 0.0 ms (23.4 ± 2.1 draws) 2.5 ± 0.5 ms (192.7 ± 37.6 draws)
CN1CCC[C@H]1c1cccnc1 12 136 11.3 ± 0.7 ms 22.3 ± 2.0 ms 24.5 ± 1.7 ms 11.4 ± 0.7 ms 12.9 ± 0.5 ms 2.8 ± 0.4 ms (93.1 ± 5.5 draws) 32.9 ± 8.2 ms (986.9 ± 195.7 draws)
CNC(=O)O/N=C(\C)SC 10 72 13.1 ± 3.2 ms 30.9 ± 1.9 ms 31.0 ± 2.2 ms 22.8 ± 0.9 ms 25.6 ± 1.2 ms 1.1 ± 0.4 ms (51.3 ± 6.1 draws) 6.2 ± 1.2 ms (411.0 ± 78.5 draws)
N[C@@H](Cc1ccc(O)c(O)c1)C(=O)O 14 688 16.2 ± 0.7 ms 69.6 ± 3.4 ms 72.5 ± 2.3 ms 47.7 ± 3.7 ms 57.0 ± 4.4 ms 10.4 ± 0.6 ms (514.6 ± 20.6 draws) 142.7 ± 17.9 ms (7024.4 ± 654.9 draws)
COc1ccc2cc([C@H](C)C(=O)O)ccc2c1 17 1504 24.8 ± 1.2 ms 160.6 ± 8.7 ms 165.8 ± 11.6 ms 131.9 ± 17.9 ms 138.7 ± 3.2 ms 32.2 ± 2.4 ms (1160.9 ± 44.3 draws) 523.4 ± 111.4 ms (20279.3 ± 3306.9 draws)
O=[N+]([O-])O[C@H]1CO[C@H]2[C@@H]1OC[C@H]2O[N+](=O)[O-] 16 1240 24.9 ± 2.4 ms 133.3 ± 15.4 ms 141.6 ± 6.0 ms 85.1 ± 3.4 ms 119.0 ± 13.4 ms 20.0 ± 0.7 ms (983.9 ± 28.0 draws) 396.9 ± 72.5 ms (18416.3 ± 2617.4 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 160.8 ± 16.7 ms 3372.9 ± 200.9 ms 3802.8 ± 289.8 ms 3015.1 ± 58.5 ms 3308.2 ± 121.7 ms 173.9 ± 10.8 ms (4709.1 ± 35.5 draws) 5060.8 ± 910.8 ms (148845.6 ± 23587.3 draws)
CC1=C(CC(=O)O)c2cc(F)ccc2/C1=C\c1ccc(S(C)=O)cc1 25 12096 344.5 ± 16.4 ms 10382.1 ± 351.3 ms 9194.2 ± 537.5 ms 9720.7 ± 370.2 ms 9248.5 ± 441.5 ms 341.3 ± 11.7 ms (9570.0 ± 78.4 draws) 9815.2 ± 1144.8 ms (269236.4 ± 30102.1 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