Blaise list micro-benchmark — results log
==========================================

Each entry records the median of two consecutive runs of
tests/bench_lists.pas, taken on the machine identified in the entry
header.  Add new entries below the previous one (newest at the
bottom) so the file forms a chronological trend.

Workloads (all in one program):
  - TStringList     vs  TList<String>
  - TObjectList     vs  TList<TObject>

Phases (all ms wall-clock):
  insert         1,000,000 Adds (item_<i> strings or fresh TItem instances)
  sequential     Get(i) over the full list (linear sweep)
  random         1,000,000 indexed reads in a pseudo-random pattern
                 (deterministic LCG, seed=42)
  for..in        full enumeration via the for-in protocol
                 (strings benchmark only; objects benchmark omits this)
  IndexOf/scan   1,000 lookups on the list (TList<T> uses a hand-rolled
                 linear scan since it has no IndexOf method).  Note: the
                 string benchmark searches a 100,000-item list; the object
                 benchmark searches the full 1,000,000-item list.


------------------------------------------------------------------------
2026-05-21 — Graeme @ AMD Ryzen 7 5800X (Linux 6.14)
  Blaise compiler v0.9.0-dev
  Commit:        93358ed (fix codegen ARC for ^TClass writes)

  --- bench_strings ---
                                                TStringList    TList<String>
    insert 1_000_000                                  98 ms          90 ms
    sequential Get(i) x Count                         10 ms          10 ms
    random  Get(i)  x 1_000_000                       19 ms          19 ms
    for..in over 1_000_000                            15 ms          11 ms
    IndexOf / hand-rolled scan x 1000                590 ms         277 ms

  --- bench_objects ---
                                                TObjectList    TList<TObject>
    insert 1_000_000                                  36 ms          41 ms
    sequential Get(i) x Count                          4 ms           6 ms
    random  Get(i)  x 1_000_000                       10 ms          13 ms
    IndexOf / hand-rolled scan x 1000                 16 ms         131 ms

  Notes:
    * TList<String> beats TStringList across every phase; the
      TStringList.IndexOf cost includes sorted-mode/duplicates checks
      the hand-rolled scan does not, hence the 2x gap.
    * TObjectList beats TList<TObject> on writes and reads (raw pointer
      storage vs. typed ^T with ARC), and is dramatically faster on
      IndexOf because the call goes via a direct pointer scan in a
      single function instead of one method call per element.
    * The compiler currently miscompiles a program that instantiates
      the same generic class with two different concrete arguments
      (e.g. TList<String> and TList<TObject> in one program) — that is
      why the benchmark is split into two files.  (Fixed in a later
      commit via per-instance AST body cloning.)


------------------------------------------------------------------------
2026-05-21 — Graeme @ AMD Ryzen 7 5800X (Linux 6.14)
  Blaise compiler v0.9.0-dev
  Commit:        b6736d3 (fix semantic: clone method bodies per generic instance)

  --- merged into a single program (tests/bench_lists.pas) ---
                                                TStringList    TList<String>
    insert 1_000_000                                  99 ms          89 ms
    sequential Get(i) x Count                         10 ms          10 ms
    random  Get(i)  x 1_000_000                       20 ms          19 ms
    for..in over 1_000_000                            15 ms          11 ms
    IndexOf / hand-rolled scan x 1000                681 ms         287 ms

                                                TObjectList    TList<TObject>
    insert 1_000_000                                  36 ms          40 ms
    sequential Get(i) x Count                          4 ms           6 ms
    random  Get(i)  x 1_000_000                        9 ms          13 ms
    IndexOf / hand-rolled scan x 1000                 16 ms         131 ms

  Notes:
    * Multi-instance generic miscompile is fixed — TList<String> and
      TList<TObject> now co-exist in one program, so the two split
      benchmarks have been merged into tests/bench_lists.pas.
    * Numbers are within noise of the previous split-program run on
      the same hardware; combining the workloads does not perturb
      timings.


------------------------------------------------------------------------
2026-05-21 — Graeme @ AMD Ryzen 7 5800X (Linux 6.14)
  Blaise compiler v0.9.0-dev
  Commit:        ffe09b3 (perf codegen: elide _ClassRelease on provably-nil slots)

                                                TStringList    TList<String>
    insert 1_000_000                                  96 ms          90 ms
    sequential Get(i) x Count                         11 ms          11 ms
    random  Get(i)  x 1_000_000                       19 ms          19 ms
    for..in over 1_000_000                            15 ms          11 ms
    IndexOf / hand-rolled scan x 1000                600 ms         283 ms

                                                TObjectList    TList<TObject>
    insert 1_000_000                                  37 ms          42 ms
    sequential Get(i) x Count                          4 ms           5 ms
    random  Get(i)  x 1_000_000                        9 ms          12 ms
    IndexOf / hand-rolled scan x 1000                 16 ms          90 ms

  Notes:
    * Big win on the TList<TObject> hand-rolled scan (~30% faster:
      131 ms -> 90 ms).  Source: nil-slot _ClassRelease elision in the
      codegen — TList<T>.Get's `Result := Src^` no longer emits a
      release-on-nil pair, saving one cross-TU call per Get.
    * Smaller incidental wins on Sequential Get (6->5 ms) and Random
      Get (13->12 ms) for TList<TObject> from the same change.
    * TList<String> hand-rolled scan unchanged at 283 ms; the elision
      applies to class-typed assignments only.  Strings get the same
      treatment if we extend the optimisation to strings in a follow-up.
    * TStringList.IndexOf dropped 681->600 ms.  Cause uncertain; may
      just be run-to-run noise.
