Files
node/utils/math/meter/continuous_meter.go
zeekay 7cf87b230b node-unified is the node
The module already called itself github.com/luxfi/node while containing no node
in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and
the Go column of the matrix measured a VM plugin. A repo that fetches the thing
it claims to be has not replaced it, so the Go sources move in — 1515 files,
the daemon and everything under it — and the build reaches outside this module
for nothing.

Rust and C++ sit beside it unchanged and are still measured against it by the
differential. That is the point of one repo: the reference implementation and
the two ports are the same checkout, so parity is a thing you can run rather
than a thing you assert.

Verified: builds, and the closure carries no lux-private — checked at build time
rather than believed. The daemon starts twelve chains on a local network
(P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
2026-09-07 16:15:25 -07:00

78 lines
1.7 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package meter
import (
"math"
"time"
)
var (
_ Factory = (*ContinuousFactory)(nil)
_ Meter = (*continuousMeter)(nil)
)
// ContinuousFactory implements the Factory interface by returning a continuous
// time meter.
type ContinuousFactory struct{}
func (ContinuousFactory) New(halflife time.Duration) Meter {
return NewMeter(halflife)
}
type continuousMeter struct {
halflife float64
value float64
numCoresRunning float64
lastUpdated time.Time
}
// NewMeter returns a new Meter with the provided halflife
func NewMeter(halflife time.Duration) Meter {
return &continuousMeter{
halflife: float64(halflife) / math.Ln2,
}
}
func (a *continuousMeter) Inc(now time.Time, numCores float64) {
a.Read(now)
a.numCoresRunning += numCores
}
func (a *continuousMeter) Dec(now time.Time, numCores float64) {
a.Read(now)
a.numCoresRunning -= numCores
}
func (a *continuousMeter) Read(now time.Time) float64 {
timeSincePreviousUpdate := a.lastUpdated.Sub(now)
if timeSincePreviousUpdate >= 0 {
return a.value
}
a.lastUpdated = now
factor := math.Exp(float64(timeSincePreviousUpdate) / a.halflife)
a.value *= factor
a.value += a.numCoresRunning * (1 - factor)
return a.value
}
func (a *continuousMeter) TimeUntil(now time.Time, value float64) time.Duration {
currentValue := a.Read(now)
if currentValue <= value {
return time.Duration(0)
}
// Note that [factor] >= 1
factor := currentValue / value
// Note that [numHalfLives] >= 0
numHalflives := math.Log(factor)
duration := numHalflives * a.halflife
// Overflow protection
if duration > math.MaxInt64 {
return time.Duration(math.MaxInt64)
}
return time.Duration(duration)
}