verbs/put/put.js appendAndAssign is O(N^2) + re-rolls ulog ts
be put a b c … lowers each path arg to its own handler call, and each call's commitOps invokes appendAndAssign, which DRAINS the whole wtlog, concatenates the new rows, and rewrites the entire file (temp + fsync + rename) — once per arg. A wide arg list is quadratic plus N temp-file cycles. It also HAND-ROLLS ulog's monotonic-stamp policy (nowAfter(tail) then +1 per row) instead of calling the shared writer, so any future ts-policy change diverges silently. ulog.appendInPlace/feedRows exist for exactly this. Output is correct today (put rows carry no per-row ts in the tree), so the divergence is latent. Method: Issues.
verbs/put/put.js:152 commitOps calls `appendAndAssign(repo.bePath, rows,floorTs)` per non-silent arg-batch.
:170-174 appendAndAssign re-reads ALL old rows via ulog.each into
old[] every call (the O(N) drain).
:175-184 re-derives tail, ulog.nowAfter(tail), the floorTs floor,
and the per-row ts = ts + 1n bump — a copy of ulog.feedRows/append.
:185 ulog.write(bePath, old.concat(fresh)) rewrites the whole ULOG
(temp _stage + io.rename) — the O(N) write, paid once per arg → O(N^2).
shared/ulog.js:181 appendInPlace(path, rows, ts) books ONE container and
feeds at the watermark (no whole-file drain); :190 feedRows owns the nowAfter+floor++1 stamp policy appendAndAssign re-implements.
container (or one streaming append) carries the batch.
ulog (feedRows/appendInPlace), not asecond hand-rolled copy in put.js.
:159-160 reads it).verbs/put/put.js + maybe a small shared/ulog.js helper; keep the row
shapes (put <path> / put <path>#<dst>) and floorTs cohort behaviour.
be put a b c.ulog.appendInPlace once for the whole batch and re-read
the tail to recover assigned ts, or (b) add an ulog helper that feeds and RETURNS the assigned ts array (the one bit appendAndAssign needs that feedRows does not expose) — preferred, kills the duplication outright.
appendAndAssign then becomes a thin wrapper over the shared helper.test/js/put/*: multi-arg put a b c asserts each file'srestamp mtime == its staged row ts, and the wtlog is byte-identical to native; instrument to confirm ONE write, not N.
ulog.feedRowsAssign (feed + return assigned ts) or reuse
appendInPlace; route appendAndAssign through it.
appendInPlace does not currently return assigned ts — needs the smallhelper or a tail re-read; pick one.
928aaad5
RETIRED ulog.appendInPlace/feedRows with core/job.js (shared/ulog.js:246 note). verbs/put/put.js:198 appendAndAssign still drains all rows (ulog.each:200) + rewrites the whole file (ulog.write:213), called per arg-batch (:449,:502,:660,:681). The fix must re-introduce a streaming append helper (they no longer exist) or add one to ulog.js.