Skip to content

dmp: bound diffs by work (diffWorkLimit 25M), not the clock (P3 of #26) - #30

Merged
williamstein merged 2 commits into
mainfrom
feat/dmp-work-limit
Oct 21, 2026
Merged

williamstein merged 2 commits into
mainfrom
feat/dmp-work-limit

Conversation

@williamstein

Copy link
Copy Markdown
Contributor

Bound diffs by @cocalc/diff-match-patch's deterministic work budget (diffWorkLimit, new in 1.1.0) instead of the clock (diffTimeout = 0.2).

Why

diffTimeout cuts a diff off by wall-clock time. So the same two texts give a different diff, a different patch and a different patch size depending on how fast and how loaded the machine is: a commit's patch isn't reproducible. diffWorkLimit cuts it off after a fixed amount of abstract work, so the same inputs give the same patch everywhere. This is step P3 of #26 (a deterministic diff bound).

The change

  • src/dmp.ts: dmp.diffWorkLimit = DIFF_WORK_LIMIT (25,000,000, exported) replaces dmp.diffTimeout = 0.2. When set, diffWorkLimit replaces diffTimeout, and the clock is never read. That covers makePatch / patchMake, diffMain, and applyPatch's fuzzy matching diffs.
  • The figure: 25M units take about 0.2 s on V8 (Node) on an AMD EPYC 7B13 core (the dmp README), so the cutoff is about where it was. That's a measurement there, not a guarantee and not part of the contract.
  • The bound: the contract bounds the diff's charged steps to diffWorkLimit + 24 × (n + 2). It doesn't bound all of patch_make, whose assembly and context search are linear in 1.1.0 (dmp#2).
  • package.json: @cocalc/diff-match-patch ^1.0.0 → ^1.1.0. The lockfile changes only those three dmp lines. pnpm also wanted to bump tinyglobby's picomatch; I left that out.
  • src/merge3.ts is unchanged. It already uses diffTimeout = 0 and bounds its own work deterministically with MAX_DIFF_PRODUCT.

Compatibility

Only newly made patches change, and only for diffs large enough to hit the cutoff. Below it, both settings give the exact diff. Stored patches, and applying them, are unaffected. Patches made by replicas on 0.14.0 and on this release are equally valid.

Tests (src/dmp-work-limit.test.ts, 3)

  • It never reads the clock: with a Date.now that throws, makePatch, diffMain and applyPatch still work, both on small texts and on a 100,000-character pair of unrelated texts whose diff the budget cuts off.
  • The same patch whatever the clock says: a clock that's frozen, racing a minute per read, or a century ahead gives the same patch.
  • Both tests fail with diffTimeout = 0.2. I checked by reverting the line.

Checks

  • vitest run: 22 files, 223 passed (1 skipped).
  • oxlint --deny-warnings src: clean. tsc (types, CJS), rollup (ESM) and postbuild: OK.
  • Prettier is clean on the changed files.

Note on CI: release age

The repo's pnpm policy, minimumReleaseAge, is one day. dmp 1.1.0 was published at 2026-10-21T07:13:59Z, so pnpm install --frozen-lockfile refuses it until about 2026-10-22 07:14 UTC. CI fails at install until then. I'll re-run it after that time. I haven't changed the policy (no minimumReleaseAgeExclude): that's William's call. The tests above ran locally against the installed 1.1.0.

Not in this PR

  • The release: William merges and releases patchflow.
  • CoCalc pinning the new patchflow: a separate CoCalc PR after the release.

Owner: @cocalc-dev-lite2 on cocalc.ai, project lite2 - cocalc #dev (1c8ec4b3)

…get (diffWorkLimit 25M) instead of diffTimeout 0.2

The same two texts now give the same patch on any machine, however fast or
loaded; 25M units are about 0.2 s on V8 on an AMD EPYC core (dmp README).
Requires @cocalc/diff-match-patch ^1.1.0.
@williamstein
williamstein marked this pull request as ready for review October 21, 2026 07:50
1.1.0 was published by us via npm trusted publishing on 2026-10-21; the
new-release guard protects against malicious third-party releases and
does not apply to our own package. Approved by William (Oct 21).
@williamstein

Copy link
Copy Markdown
Contributor Author

Merge evidence (@sagebrush): head d32e70a. William approved merging #30 when green (Oct 21), and approved overriding the minimumReleaseAge guard for our own @cocalc/diff-match-patch 1.1.0 (published by us via trusted publishing). Commit d32e70a adds minimumReleaseAgeExclude: ["@cocalc/diff-match-patch"] to pnpm-workspace.yaml; the lockfile is unchanged. CI run 39672023578: success (install, audit, check). Locally, pnpm install --frozen-lockfile and pnpm check pass.

@williamstein
williamstein merged commit 5f1416a into main Oct 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant