Released 1.1.5 desktop throughput baseline¶
Date: 2026-10-02. Six alternating shown/minimized samples were scheduled on one disposable macOS Obsidian instance per sample. Five completed; sample 5 failed before recording measurements. This gives two complete pairs, not the three required for the planned comparison. The campaign does not close #262 or #274 or #283.
Artifacts and method¶
All six build.json receipts identify clean released 1.1.5 source
03d108505d3993bddff276d70c814a6547222339 and these SHA-256 values:
| Artifact | SHA-256 |
|---|---|
obsyncd |
5c7b0af778c5162b5915ebc4c4f0114a3e6d874ae5f547ac1096aa9878d41804 |
main.js |
34797c29613f28104157e09de46dc713be862269bdebca11c587ebe8c2522b11 |
manifest.json |
ed84bd8d8d6f4e316d96ecddc8e097704a8719367781ac35d61cff7b4dba463d |
styles.css |
43dd0db8ccce20e88a3c63ec2ea35e46ce4133912c0e797da036e37a6499287b |
Each sample used a fresh vault, account and server with the same 7,700
synthetic notes: 11,565,400 bytes, fixture digest
637f4bea6f1ed029d67f4099120cf4961592f1f146137411b2dc6aa4b1b3e42b.
The local server was reached through a temporary public HTTPS tunnel with
certificate verification enabled. This was not either reference deployment
route or Community Plugins installation proof. Security checks and durable
acknowledgments were unchanged. The campaign did not separately record the
host OS/app version or a cold/warm filesystem-cache classification.
The frozen harness first opened and trusted the owned vault, attached
measurement observers, set the window state, and completed native account
setup and phrase confirmation. It observed normal push completion logs and
completed saveData calls without replacing those operations. Minimized
samples stayed minimized for at least ten minutes, including the interval
after first sync. A subsequent Sync now was timed until its drained log.
Reconstructing the campaign harness¶
The retained six-file snapshot is evidence, not a standalone executable
bundle. lab.py requires a Git worktree with the harness installed at
scripts/validation/lab; journeys.mjs also imports
../../ci/obsidian-drive.mjs. Start with that support file from baseline commit
03d108505d3993bddff276d70c814a6547222339, SHA-256
ad9d047b12186ea3814c0a25393aee765a6f11538cd367dc299c99b61ef3d399.
The baseline file needs the explicit import adapter below: export the seven
UI helpers and run its own journey only when invoked directly. The resulting
file has SHA-256
0624d49ede7c9e027e5816f510ca60c1b0f7cccc8c826b4df57f0702385e6acc.
That support file was not included in the campaign snapshot; this pins a
reconstruction, not independently retained historical support-file bytes.
Set BASELINE_CHECKOUT to the already built baseline checkout,
FROZEN_HARNESS to the retained snapshot, and HARNESS_CHECKOUT to a new
disposable worktree path. Reconstruct the layout without changing either
retained input:
git -C "$BASELINE_CHECKOUT" worktree add --detach "$HARNESS_CHECKOUT" \
03d108505d3993bddff276d70c814a6547222339
HARNESS="$HARNESS_CHECKOUT/scripts/validation/lab"
python3 -B - "$FROZEN_HARNESS" "$HARNESS" <<'PY'
import hashlib, json, shutil, sys
from pathlib import Path
source, destination = map(Path, sys.argv[1:])
files = json.loads((source / "sha256.json").read_text())["files"]
assert set(files) == {"lab.py", "cdp.mjs", "journeys.mjs", "performance.py",
"performance.mjs", "fixture.py"}
destination.mkdir(parents=True)
for name, digest in files.items():
assert hashlib.sha256((source / name).read_bytes()).hexdigest() == digest
shutil.copyfile(source / name, destination / name)
support = destination / "../../ci/obsidian-drive.mjs"
assert hashlib.sha256(support.read_bytes()).hexdigest() == \
"ad9d047b12186ea3814c0a25393aee765a6f11538cd367dc299c99b61ef3d399"
text = support.read_text()
entry = "\nmain().catch((error) => {"
assert text.count(entry) == 1
exports = "export { click, fillSetting, fillPlaceholder, settingsShow, " \
"confirmPhrase, pairingCode, LABELS };"
support.write_text(text.replace(entry, "\n" + exports +
"\n\nif (import.meta.main) main().catch((error) => {"))
assert hashlib.sha256(support.read_bytes()).hexdigest() == \
"0624d49ede7c9e027e5816f510ca60c1b0f7cccc8c826b4df57f0702385e6acc"
PY
python3 -B "$HARNESS/performance.py" --help
This reconstruction was checked with --help, the six snapshot hashes, both
support-file hashes, and relative-import/export resolution on Node 26.10.0.
Those checks did not start
a lab or replay the measurements. A separately authorized campaign then uses
new external output paths and the required native app/TLS route:
python3 -B "$HARNESS/performance.py" \
--source-repo "$BASELINE_CHECKOUT" --run "$NEW_EXTERNAL_RUN" \
--fixture "$EXTERNAL_FIXTURE" --notes 7700 --pairs 3 \
--tunnel "$APPROVED_TUNNEL_EXECUTABLE"
A later portable harness revision is not the frozen campaign harness.
Frozen performance.py SHA-256:
e4ff07c6cfc15f7a164d9e3c6881b1541d365871ad300a65386f3ccb8e0807ce.
Frozen performance.mjs SHA-256:
01cb1bd0a720986f40bb973259be5d3a55a50d76d25958721d866b1db30987ad.
The six-file snapshot and its complete checksum manifest remain outside the
repository with the synthetic fixture and raw evidence.
Every scheduled sample¶
Upload span is the time between the first and last of 7,700 completed pushes.
Throughput is 7699 * 1000 / upload_span_ms; it excludes account setup and
other time before the first push. Sync now is a later full-vault drain, not
part of that span. Failure rows stay in the scheduled sample count.
| Sample | Window | Completed pushes | Upload span | Notes/s | Sync now | Minimized duration |
|---|---|---|---|---|---|---|
| 1 | Shown | 7,700 | 247.864 s | 31.061 | 3.345 s | — |
| 2 | Minimized | 7,700 | 264.411 s | 29.118 | 3.392 s | 604.926 s |
| 3 | Shown | 7,700 | 248.954 s | 30.925 | 3.368 s | — |
| 4 | Minimized | 7,700 | 261.662 s | 29.423 | 3.466 s | 605.318 s |
| 5 | Shown requested | No measurement | — | — | — | — |
| 6 | Minimized | 7,700 | 257.232 s | 29.930 | 3.394 s | 604.903 s |
The complete pairs' minimized/shown throughput ratios are 0.937419 (samples 2/1) and 0.951434 (4/3). Their Sync now duration ratios are 1.014051 and 1.029097. Sample 6 has no measured shown partner; it is not paired with a different attempt. Both pairs meet the pre-run thresholds: minimized throughput at least 0.8 times shown and Sync now duration at most 1.2 times shown. They do not establish the required three-pair comparison, proven idle conditions or restoration on idle, cancel, error and unload.
Seventh-thousand rate and bookkeeping saves¶
Each thousand rate uses 1,000 intervals between recorded completed pushes:
1000000 / (pushed[start + 1000] - pushed[start]), at starts 0 and 6,000.
Saves count completed saveData calls from account-setup start through the
first observed 7,700-push idle state, divided by 77 for the per-100 figure.
They do not measure physical disk-write bytes or serialization time.
| Sample | First thousand notes/s | Seventh thousand notes/s | Seventh / first | Saves in first-sync window | Saves / 100 notes |
|---|---|---|---|---|---|
| 1 | 29.732 | 31.183 | 1.048801 | 243 | 3.155844 |
| 2 | 28.305 | 30.487 | 1.077101 | 254 | 3.298701 |
| 3 | 31.554 | 30.836 | 0.977243 | 246 | 3.194805 |
| 4 | 29.847 | 26.976 | 0.903804 | 252 | 3.272727 |
| 5 | — | — | — | — | — |
| 6 | 28.293 | 29.354 | 1.037514 | 249 | 3.233766 |
All five measured seventh/first ratios fall within 0.90–1.10. The campaign records the missing rate metric for these samples. It did not inject a crash between the server answer and state persistence, independently verify stable file identity after restart, or measure rewritten bytes, serialization time and editor responsiveness required by #274's follow-up. It supplies no new crash-recovery acceptance.
Load and failures¶
The coordinator reserved a quiet work window, but the machine was not proven idle. At each sample's first recorded CPU snapshot, idle percentages were 23.71, 32.60, 21.65, 17.10, 35.94 and 28.15 respectively. The snapshots and start/end load averages are retained. They neither isolate the source of load nor establish a causal explanation for the rates or failures. This campaign must not be compared as a proven idle baseline against a loaded run.
Sample 5 completed initialization, measurement preparation and native setup.
Its initial measurement evaluation then refused or timed out; there is no
window.json, progress series or performance result. The sanitized failure
record omitted the safe window/measurement fields needed to distinguish the
cause. Its whole attempt lasted 25.273 s including setup and teardown; that
is not an upload measurement. Cause: UNKNOWN. The failed sample was kept
and the remaining scheduled sample ran; it was not replaced by a retry.
Follow-up calibration and diagnostic boundary¶
After freezing that campaign, the measurement harness was changed to save safe window fields before evaluating the window-state guard. A separate three-attempt, 20-note shown-window calibration produced:
| Attempt | Observed result |
|---|---|
| 1 | Measurement present; shown, not minimized; zero recorded window mismatches; setup started; 20 pushes completed |
| 2 | Same observed control result; 20 pushes completed |
| 3 | Failed native phrase-confirmation deadline during setup, before a measurement result |
Those two successful controls do not explain sample 5 or replace its missing measurement. The third calibration failure is a different observed stage; its underlying cause is also unresolved.
A subsequent private setup diagnostic added safe booleans/counts for owned
windows and console-summary counts to the harness source. It did not print
phrase words, pairing codes, credentials or arbitrary exception text. Three
scheduled diagnostic attempts failed at launcher readiness parsing with
JSONDecodeError; their teardown receipts record sandbox refusal before
manifest creation or process launch. One isolated launcher check had the
same pre-launch boundary. All four report zero created processes and no
runtime. They provide no app diagnostic result and no evidence of a product
setup failure. Source addition is distinct from an executed diagnostic.
Retention and teardown¶
All six performance attempts and all three calibration attempts have teardown receipts with zero owned process groups, zero holders and no runtime directory. The four pre-launch diagnostic receipts also report no runtime; directory absence was checked again while preparing this record. Raw metrics, failures, source snapshots and sanitized receipts remain outside the product repository.
Result-file SHA-256 references:
- Six-sample campaign:
397acc6a61170c79055f8a9303395a47fa8099eb68f5496c8f4660ca725b85e2. - Three-attempt calibration:
b3b7105db47cadc5dc3794282fa62151ce54aec8bef03d8c4e05d022b932aabb. - Three-attempt setup diagnostic:
72715c2e7f4bf6cf943ddb9be42e3e57867d88bbf2168d425c6abfbe9d71c00b.
Phone behavior, concurrent typing, energy, peak RSS, network bytes, complete idle CPU/wakeup distributions, independent peer readback and the final candidate's before/after comparison were not established by this campaign.