Improved perfs

This commit is contained in:
Martino Ferrari
2026-05-12 10:16:48 +02:00
parent 912ecdd9ed
commit 6ff8fb5c25
14 changed files with 1357 additions and 25 deletions
+48 -5
View File
@@ -5,6 +5,7 @@ package stub
import (
"context"
"fmt"
"math"
"math/rand/v2"
"sync"
@@ -13,11 +14,12 @@ import (
"github.com/uopi/uopi/internal/datasource"
)
const updateInterval = 100 * time.Millisecond // 10 Hz
const updateInterval = 100 * time.Millisecond // 10 Hz default
type signalDef struct {
meta datasource.Metadata
fn func(t time.Time) any
meta datasource.Metadata
interval time.Duration // 0 → updateInterval
fn func(t time.Time) any
}
// Stub is a data source that emits canned signals for development and testing.
@@ -96,6 +98,41 @@ func New() *Stub {
fn: func(t time.Time) any { return 25.0 }, // default; overwritten by Write
})
s.values["setpoint"] = 25.0
s.register(signalDef{
meta: datasource.Metadata{
Name: "counter_fast", Type: datasource.TypeFloat64,
Description: "Fast monotonic counter (1 ms tick) for benchmarks",
},
interval: time.Millisecond,
fn: func(t time.Time) any { return float64(t.UnixMilli()) },
})
return s
}
// NewN creates a Stub with n dynamically generated signals named "pv_0" … "pv_{n-1}".
// Each signal is a sine wave at a distinct frequency, emitted at 10 Hz.
// Use this for stress and scale testing.
func NewN(n int) *Stub {
s := &Stub{
signals: make(map[string]signalDef),
values: make(map[string]any),
}
for i := range n {
freq := 0.1 + float64(i)*0.01 // spread frequencies so signals differ
s.register(signalDef{
meta: datasource.Metadata{
Name: fmt.Sprintf("pv_%d", i),
Type: datasource.TypeFloat64,
Unit: "V",
DisplayLow: -1,
DisplayHigh: 1,
Description: fmt.Sprintf("Synthetic PV #%d (%.2f Hz sine)", i, freq),
},
fn: func(t time.Time) any {
return math.Sin(2 * math.Pi * freq * float64(t.UnixNano()) / 1e9)
},
})
}
return s
}
@@ -127,16 +164,22 @@ func (s *Stub) GetMetadata(_ context.Context, signal string) (datasource.Metadat
return d.meta, nil
}
// Subscribe starts a 10 Hz ticker that pushes generated values into ch.
// Subscribe starts a ticker that pushes generated values into ch.
// The tick interval is the signal's configured interval (default 10 Hz).
func (s *Stub) Subscribe(ctx context.Context, signal string, ch chan<- datasource.Value) (datasource.CancelFunc, error) {
def, ok := s.signals[signal]
if !ok {
return nil, datasource.ErrNotFound
}
interval := def.interval
if interval == 0 {
interval = updateInterval
}
ctx, cancel := context.WithCancel(ctx)
go func() {
ticker := time.NewTicker(updateInterval)
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {