mirror of
https://github.com/hanzoai/insights-go.git
synced 2026-09-30 22:46:12 +00:00
Addresses high RAM usage and OOMs when using feature flags at scale. Tested with 853 flags + 12 cohorts (production-like setup): Before: 17,463 allocs/op, 201 MB/op, 51 ms/op After: 139 allocs/op, 56 KB/op, 129 µs/op Key changes: - Cache flagsByKey in flagsState at load time (was O(N²) in GetAllFlags) - sha1.Sum with stack buffer instead of sha1.New + hash.Write (zero heap escapes) - Append '.' separator inside calculateHash buffer (avoid string concat alloc) - Cache getSystemContext/getVersion with sync.Once - Pre-compute at load time: variant lookup tables, decoded payloads, parsed cohort values - Cache compiled regexps via sync.Map - Eliminate double flag evaluation (single-pass GetFeatureFlagWithPayload) - Lazy evaluationCache only for flags with dependencies - Sentinel errors + direct type assertions replacing errors.As - valueToString replacing fmt.Sprintf throughout matchProperty - Defer empty map allocation in validate() to remote path only - Pre-merge distinct_id once before GetAllFlags loop - Embed payload/variant strings in FeatureFlagResult struct - Skip Properties merge for flags without person property conditions
58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
package posthog
|
|
|
|
import (
|
|
"runtime"
|
|
"sync"
|
|
)
|
|
|
|
type osInfo struct {
|
|
Name string `json:"$os"`
|
|
Version string `json:"$os_version,omitempty"`
|
|
Distro string `json:"$os_distro,omitempty"`
|
|
}
|
|
|
|
type sysContext struct {
|
|
osInfo
|
|
GoVersion string `json:"$go_version"`
|
|
}
|
|
|
|
// cachedSystemContext holds the cached system context, computed once per process.
|
|
// OS info and Go version don't change during runtime, so there's no need to
|
|
// re-compute (and re-exec sw_vers/uname) on every event.
|
|
var (
|
|
cachedSystemContext sysContext
|
|
cachedSystemContextOnce sync.Once
|
|
// cachedSysContextProps holds the pre-built properties from the cached system context.
|
|
// This avoids creating a new Properties map on every ToProperties() call.
|
|
cachedSysContextProps Properties
|
|
cachedSysContextPropsOnce sync.Once
|
|
)
|
|
|
|
func getSystemContext() sysContext {
|
|
cachedSystemContextOnce.Do(func() {
|
|
cachedSystemContext = sysContext{
|
|
osInfo: getOSInfo(),
|
|
GoVersion: runtime.Version(),
|
|
}
|
|
})
|
|
return cachedSystemContext
|
|
}
|
|
|
|
func (ctx sysContext) ToProperties() Properties {
|
|
cachedSysContextPropsOnce.Do(func() {
|
|
sc := getSystemContext()
|
|
props := Properties{
|
|
"$os": sc.Name,
|
|
"$go_version": sc.GoVersion,
|
|
}
|
|
if sc.Version != "" {
|
|
props["$os_version"] = sc.Version
|
|
}
|
|
if sc.Distro != "" {
|
|
props["$os_distro"] = sc.Distro
|
|
}
|
|
cachedSysContextProps = props
|
|
})
|
|
return cachedSysContextProps
|
|
}
|