Cache runtime version metadata fallback
This commit is contained in:
@@ -48,7 +48,7 @@ reports these implemented packages:
|
|||||||
| `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. |
|
| `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. |
|
||||||
| `internal/validation` | Shared Go validation with optional race, full-vet, and static package-compilation target selections, formatting, workspace-file and filesystem-replacement checks, per-blob size limits, and selected Markdown destination and fragment checking; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. |
|
| `internal/validation` | Shared Go validation with optional race, full-vet, and static package-compilation target selections, formatting, workspace-file and filesystem-replacement checks, per-blob size limits, and selected Markdown destination and fragment checking; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. |
|
||||||
| `internal/publish` | Publication guards, one validation run, annotated tag creation, push, and recovery state. |
|
| `internal/publish` | Publication guards, one validation run, annotated tag creation, push, and recovery state. |
|
||||||
| `internal/runtimeinfo` | Private version lookup used by the runtime facade. |
|
| `internal/runtimeinfo` | Injected version selection and cached fallback metadata lookup for the runtime facade. |
|
||||||
| `internal/versioncontract` | Shared stable-version rules and linker-symbol identity. |
|
| `internal/versioncontract` | Shared stable-version rules and linker-symbol identity. |
|
||||||
|
|
||||||
The `buildinfo` facade depends only on its small runtime implementation. The
|
The `buildinfo` facade depends only on its small runtime implementation. The
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Computational Efficiency Implementation Plan
|
# Computational Efficiency Implementation Plan
|
||||||
|
|
||||||
**Status:** Stages 1–9 complete; Stages 10–11 pending.
|
**Status:** Stages 1–10 complete; Stage 11 pending.
|
||||||
|
|
||||||
## Purpose And Baseline
|
## Purpose And Baseline
|
||||||
|
|
||||||
@@ -539,6 +539,19 @@ Run facade/dependency checks. Re-run version benchmarks after initializing the
|
|||||||
cache and report initialization separately from repeated access. The runtime
|
cache and report initialization separately from repeated access. The runtime
|
||||||
facade and its dependency boundary retain their existing public shape.
|
facade and its dependency boundary retain their existing public shape.
|
||||||
|
|
||||||
|
**Completion:** Complete. `Version` returns the linker-injected value before
|
||||||
|
touching fallback state, and a private factory wraps the existing pure
|
||||||
|
selection helper with `sync.OnceValue`. A concurrent counting-reader test
|
||||||
|
confirms one metadata read and stable results; isolated unavailable and
|
||||||
|
development cases continue to resolve to `dev`. Runtime, buildinfo, facade
|
||||||
|
dependency, consumer executable, and focused race tests passed. Three version
|
||||||
|
benchmark repetitions measured injected selection at 0.75–1.03 ns with no
|
||||||
|
allocations, fallback initialization at 1.53–1.74 µs with 1,264 B/9 allocations,
|
||||||
|
and warmed production fallback access at 4.54–4.91 ns with no allocations.
|
||||||
|
The original uncached metadata call measured 1.438–1.474 µs and 1,184 B/7
|
||||||
|
allocations per access. The internal package inventory now records the cached
|
||||||
|
fallback behavior.
|
||||||
|
|
||||||
## Stage 11: Verify The Complete Implementation And Record Results
|
## Stage 11: Verify The Complete Implementation And Record Results
|
||||||
|
|
||||||
**Owners:** Affected tests and canonical internal documentation; roadmap status.
|
**Owners:** Affected tests and canonical internal documentation; roadmap status.
|
||||||
|
|||||||
@@ -18,7 +18,19 @@ func BenchmarkPerformanceVersion(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
b.Run("FallbackInitialization", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
fallback := newFallbackVersion(debug.ReadBuildInfo)
|
||||||
|
performanceVersionSink = fallback()
|
||||||
|
if performanceVersionSink == "" {
|
||||||
|
b.Fatal("fallback returned an empty version")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
b.Run("RealMetadataFallback", func(b *testing.B) {
|
b.Run("RealMetadataFallback", func(b *testing.B) {
|
||||||
|
_ = Version()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
|||||||
@@ -2,14 +2,26 @@
|
|||||||
// public buildinfo facade.
|
// public buildinfo facade.
|
||||||
package runtimeinfo
|
package runtimeinfo
|
||||||
|
|
||||||
import "runtime/debug"
|
import (
|
||||||
|
"runtime/debug"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
var injectedVersion string
|
var injectedVersion string
|
||||||
|
|
||||||
// Version returns the injected version or the running executable's main module
|
// Version returns the injected version or the running executable's main module
|
||||||
// version, falling back to "dev" when neither provides a release identifier.
|
// version, falling back to "dev" when neither provides a release identifier.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return version(injectedVersion, debug.ReadBuildInfo)
|
if injectedVersion != "" {
|
||||||
|
return injectedVersion
|
||||||
|
}
|
||||||
|
return fallbackVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
var fallbackVersion = newFallbackVersion(debug.ReadBuildInfo)
|
||||||
|
|
||||||
|
func newFallbackVersion(readBuildInfo func() (*debug.BuildInfo, bool)) func() string {
|
||||||
|
return sync.OnceValue(func() string { return version("", readBuildInfo) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func version(injected string, readBuildInfo func() (*debug.BuildInfo, bool)) string {
|
func version(injected string, readBuildInfo func() (*debug.BuildInfo, bool)) string {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package runtimeinfo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -55,3 +57,54 @@ func TestVersion(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFallbackVersionReadsMetadataOnceConcurrently(t *testing.T) {
|
||||||
|
var reads atomic.Int32
|
||||||
|
fallback := newFallbackVersion(func() (*debug.BuildInfo, bool) {
|
||||||
|
reads.Add(1)
|
||||||
|
return &debug.BuildInfo{Main: debug.Module{Version: "v4.5.6"}}, true
|
||||||
|
})
|
||||||
|
|
||||||
|
const callers = 32
|
||||||
|
results := make(chan string, callers)
|
||||||
|
var workers sync.WaitGroup
|
||||||
|
workers.Add(callers)
|
||||||
|
for i := 0; i < callers; i++ {
|
||||||
|
go func() {
|
||||||
|
defer workers.Done()
|
||||||
|
results <- fallback()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
workers.Wait()
|
||||||
|
close(results)
|
||||||
|
for result := range results {
|
||||||
|
if result != "v4.5.6" {
|
||||||
|
t.Errorf("fallback() = %q, want stable version", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if got := reads.Load(); got != 1 {
|
||||||
|
t.Fatalf("metadata reader called %d times, want once", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFallbackVersionCachesUnavailableAndDevelopmentMetadata(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
name string
|
||||||
|
read func() (*debug.BuildInfo, bool)
|
||||||
|
}{
|
||||||
|
{name: "unavailable", read: func() (*debug.BuildInfo, bool) { return nil, false }},
|
||||||
|
{name: "development", read: func() (*debug.BuildInfo, bool) {
|
||||||
|
return &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, true
|
||||||
|
}},
|
||||||
|
} {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fallback := newFallbackVersion(test.read)
|
||||||
|
if got := fallback(); got != "dev" {
|
||||||
|
t.Fatalf("fallback() = %q, want dev", got)
|
||||||
|
}
|
||||||
|
if got := fallback(); got != "dev" {
|
||||||
|
t.Fatalf("repeated fallback() = %q, want dev", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user