Repository navigation
v0.13.0
A performance and correctness-hardening release: sprints 352 and 353, the module's two deep-profiling and optimisation cycles. 100 commits, 86 closed tasks, 27 of them perf — against 4 in the whole of v0.12.0.
go.mod and go.sum are byte-identical to v0.12.0. Nothing in the supply chain moved.
Seven breaking changes — every one turns a silent failure loud
Pre-1.0 the minor digit absorbs them (docs/semver.md).
store/snapshot(#2743) andstore(#2742) now refuse a field they would previously have truncated or written unreadably. The snapshot case was discarding the WAL behind a snapshot no reader could parse. Newsnapshot.ErrFieldTooLong,txn.ErrFieldTooLong.graph/lpg(#2724, #2725, #2726) —WriteView.RemoveNodeandRemoveEdgenow returnbool. A refused removal used to be journalled for undo anyway, so rollback resurrected the node or the arc. A rolled-backDELETEalso no longer hides a committed node from older readers.store/txn(#2727) — a panic in the commit window no longer wedges every later committer. No exported symbol changed; the!marks an unexported signature.cypher(#2721) —EXPLAINandPROFILEare accepted as statement prefixes, so a Bolt driver can ask for a plan at all.
Two exported signatures broke without a ! marker and are documented as unmarked: cypher/exec.NewTop gained a parameter (#2509), and lpg.WriteView.RemoveAllEdgesFrom returns bool (#2694).
Measured against v0.12.0 — both trees, first-hand
Not carried forward: a worktree at the v0.12.0 tag and this candidate, each compiled once, run interleaved with the leading arm alternating, -race off, -count=6, load-gated. Identical go.mod between the arms means no toolchain or dependency change is mixed into any comparison — the first release since v0.11.0 for which that holds.
The noise floor was measured before anything was attributed: both arms on the same tree, 14 comparisons, 0 significant, largest drift 0.87 % sec/op, 0.00 % allocations.
| Block | geomean | Largest single move |
|---|---|---|
| Cypher count pushdown | −87.65 % | Count_LabelStarBig_Serial −99.97 % (≈3 ms → 880 ns) |
| Contended metric emission, 1→1024 | −92.79 % | IncCounterParallel −96.47 % at 1024 |
| Read transaction, 1→1024 | −73.04 % | ReadTx_LockFree −91.40 % at 1024 |
cypher/exec read-path operators |
−18.93 % | Scan_PerNode −69.97 %; Sort_10k −43.59 % |
| Columnar query shapes | −4.28 % | five hop shapes −7.7 % to −9.4 % |
search headline set (control) |
+0.83 % | within noise, as a control must be |
Contended metric emission changes sign, not degree: v0.12.0 anti-scaled (cost rising 5.8× from 1 to 1024 goroutines), v0.13.0 scales (falling 5.3×). Allocations collapse on two blocks — ReadTx_LockFree 249 → 37, Count_LabelStarBig_Serial 199,796 → 19 — and are constant across the whole ladder where v0.12.0's drifted with concurrency.
What got slower, and what this release cannot prove
Four regressions, none minimised. graph/index/btree Index_LookupHot +26.93 % (its own commit reports 6.66 %; no cause is attributed, because none was measured); Drain_Throughput +12.87 %; IncCounterParallel +8.32 % at one goroutine; CountAllNodes +3.09 %.
Sprint 353's headline index contention claims — 34.6× and 1.91× — cannot be verified at release level. No benchmark common to both trees exercises those indexes concurrently, because the instrument that measures them (bench/contention) is new here. They rest on each commit's own local A/B and are reported as such. Storage footprint, latency percentiles, and every non-darwin/arm64 host also remain unmeasured. docs/benchmarks/v0.13.0.md has the full list.
Gate
Read from inside the run log, not from a wrapper: MAKE_EXIT=0, 134 packages ok, 0 lint issues, govulncheck PASS over 136 packages in 11 modules, coverage 88.5 % aggregate with every package above its 75 % floor, and the openCypher TCK at 3897/3897 scenarios, 16006/16006 steps.
Two release blockers were found and fixed on the way, both in the instruments rather than the module: the read-path allocation gate was measuring a process-global counter that sibling goroutines contaminated (#2753), and cover-gate had never classified bench/entryheap as the instrument it declares itself to be.
Errata
The CHANGELOG entry for #2757 names a distribution route that does not exist. It says the false branch-protection claim "reached consumers" because .goreleaser.yaml bundles docs/**/* into every release tarball. Verified by extracting this release's own artefact: docs/release.md is not in the tarball, and neither is CONTRIBUTING.md. That sentence was written from reading the config instead of opening the artefact.
The substance is unaffected — the branch and tag protections genuinely do not exist, and the correction to both files stands. The claim did reach consumers, via GitHub and via go get, but not by the route named. Tracked as #2759.
That check also exposed a real packaging defect, tracked as #2758: docs/**/* matches only paths with a directory component, so 0 of 112 top-level docs/*.md files ship while 238 benchmark logs do. A consumer opening the tarball gets the evidence and none of the documentation. It will be fixed in the next release; v0.13.0 is already cached by the Go module proxy and cannot be recut.
What was delivered — from the project roadmap
3 sprint(s) closed in this release window (352, 353, 354), containing 91 tracked tasks. Every task in a closed sprint is COMPLETED: the roadmap tool refuses to close a sprint that still holds active work.
- Sprint 352 — GoGraph module deep profiling and optimization
- Sprint 353 — GoGraph Optimization Laboratory
- Sprint 354 — release GoGraph v0.13.0 to production
Source: the project roadmap (rmp), not the commit log. Sprints are attributed to a release when their close date falls after the previous tag and on or before this one. Task counts are the sprints' own membership counts, read back from the tool.
Full detail: CHANGELOG.md · release notes · benchmark record
go get github.com/FlavioCFOliveira/GoGraph@v0.13.0