From a48d3432c2aaa76a7c0c6dbe8cc62e5bab86c1aa Mon Sep 17 00:00:00 2001 From: andig Date: Sun, 5 Oct 2025 00:35:25 +0200 Subject: [PATCH] Tariffs: reduce cache cpu cycles (#24110) --- tariff/proxy.go | 31 +++++++++++++++++-------------- tariff/slots.go | 15 ++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tariff/proxy.go b/tariff/proxy.go index b8bbfd0bd..3b470a464 100644 --- a/tariff/proxy.go +++ b/tariff/proxy.go @@ -24,6 +24,7 @@ type CachingProxy struct { typ string config map[string]any + cached *cached tariff api.Tariff } @@ -150,16 +151,24 @@ func (p *CachingProxy) dynamicTariff() bool { } func (p *CachingProxy) cacheGet(until time.Time) (*cached, error) { - res, err := cacheGet(p.key) - if err != nil { - return nil, err + if p.cached == nil { + res, err := cacheGet(p.key) + if err != nil { + return nil, err + } + + p.cached = res } - if !ratesValid(res.Rates, until) { + if !ratesValid(p.cached.Rates, until) { return nil, errors.New("not enough rates") } - res.Rates = currentRates(res.Rates) + res := &cached{ + Rates: currentRates(p.cached.Rates), + Type: p.cached.Type, + } + if len(res.Rates) == 0 { return nil, errors.New("no current rates") } @@ -186,21 +195,15 @@ func untilEndOfTomorrow() time.Time { } func ratesValid(rr api.Rates, until time.Time) bool { - if len(rr) == 0 { - return false - } - - rr.Sort() - - return !rr[len(rr)-1].End.Before(until) + return len(rr) > 0 && !rr[len(rr)-1].End.Before(until) } func currentRates(rr api.Rates) api.Rates { res := make(api.Rates, 0, len(rr)) - now := now.With(time.Now()).BeginningOfHour() + now := time.Now().Truncate(SlotDuration) for _, r := range rr { - if !r.End.Before(now) { + if r.End.After(now) { res = append(res, r) } } diff --git a/tariff/slots.go b/tariff/slots.go index b8ea47a76..8ab934953 100644 --- a/tariff/slots.go +++ b/tariff/slots.go @@ -23,6 +23,10 @@ func (t *SlotWrapper) Rates() (api.Rates, error) { } var res api.Rates + if len(rates) > 0 { + // assume all slots of equal length + res = make(api.Rates, 0, len(rates)*max(int(rates[0].End.Sub(rates[0].Start)/SlotDuration), 1)) + } now := time.Now().Truncate(SlotDuration) @@ -31,14 +35,12 @@ func (t *SlotWrapper) Rates() (api.Rates, error) { continue } - interval := r.End.Sub(r.Start) - numSlots := max(int(interval/SlotDuration), 1) + numSlots := max(int(r.End.Sub(r.Start)/SlotDuration), 1) for j := range numSlots { start := r.Start.Add(time.Duration(j) * SlotDuration) end := start.Add(SlotDuration) - - var val float64 + val := r.Value switch t.Type() { case api.TariffTypeSolar: //, api.TariffTypeCo2 @@ -47,12 +49,7 @@ func (t *SlotWrapper) Rates() (api.Rates, error) { start1 := rates[i+1].Start frac := float64(start.Sub(start0)) / float64(start1.Sub(start0)) val = r.Value + frac*(rates[i+1].Value-r.Value) - } else { - val = r.Value } - - default: - val = r.Value } res = append(res, api.Rate{