в процессе, нет аккордиона, нет графика
This commit is contained in:
@@ -2,6 +2,7 @@ package adapter
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -11,29 +12,39 @@ type RingBuffer struct {
|
||||
writePtr int
|
||||
count int
|
||||
|
||||
lastWrite time.Time
|
||||
lastWrite atomic.Int64
|
||||
|
||||
// ===== SPEED METRICS =====
|
||||
totalBytes uint64
|
||||
totalBytes atomic.Uint64
|
||||
|
||||
lastTick time.Time
|
||||
lastBytes uint64
|
||||
bytesPerSec float64
|
||||
bitsPerSec float64
|
||||
// ===== SPEED =====
|
||||
lastTick atomic.Int64
|
||||
lastBytes atomic.Uint64
|
||||
|
||||
bytesPerSec atomic.Value // float64
|
||||
bitsPerSec atomic.Value // float64
|
||||
}
|
||||
|
||||
// =====================
|
||||
func NewRingBuffer(size int) *RingBuffer {
|
||||
return &RingBuffer{
|
||||
data: make([]byte, size),
|
||||
lastWrite: time.Now(),
|
||||
lastTick: time.Now(),
|
||||
rb := &RingBuffer{
|
||||
data: make([]byte, size),
|
||||
}
|
||||
|
||||
now := time.Now().UnixNano()
|
||||
|
||||
rb.lastWrite.Store(now)
|
||||
rb.lastTick.Store(now)
|
||||
|
||||
rb.bytesPerSec.Store(float64(0))
|
||||
rb.bitsPerSec.Store(float64(0))
|
||||
|
||||
return rb
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) Write(b byte) {
|
||||
rb.mu.Lock()
|
||||
|
||||
// ===== WRITE =====
|
||||
rb.data[rb.writePtr] = b
|
||||
rb.writePtr = (rb.writePtr + 1) % len(rb.data)
|
||||
|
||||
@@ -41,40 +52,45 @@ func (rb *RingBuffer) Write(b byte) {
|
||||
rb.count++
|
||||
}
|
||||
|
||||
rb.lastWrite = time.Now()
|
||||
rb.totalBytes++
|
||||
|
||||
rb.mu.Unlock()
|
||||
|
||||
// ===== SPEED CALC (outside lock) =====
|
||||
now := rb.lastWrite
|
||||
// ===== ATOMIC STATS =====
|
||||
now := time.Now().UnixNano()
|
||||
rb.lastWrite.Store(now)
|
||||
|
||||
if rb.lastTick.IsZero() {
|
||||
rb.lastTick = now
|
||||
rb.lastBytes = rb.totalBytes
|
||||
total := rb.totalBytes.Add(1)
|
||||
|
||||
// ===== SPEED CALC =====
|
||||
lastTick := rb.lastTick.Load()
|
||||
if lastTick == 0 {
|
||||
rb.lastTick.Store(now)
|
||||
rb.lastBytes.Store(total)
|
||||
return
|
||||
}
|
||||
|
||||
elapsed := now.Sub(rb.lastTick).Seconds()
|
||||
|
||||
if elapsed >= 1.0 {
|
||||
diff := rb.totalBytes - rb.lastBytes
|
||||
|
||||
rb.bytesPerSec = float64(diff) / elapsed
|
||||
rb.bitsPerSec = rb.bytesPerSec * 8
|
||||
|
||||
rb.lastTick = now
|
||||
rb.lastBytes = rb.totalBytes
|
||||
elapsed := time.Duration(now - lastTick).Seconds()
|
||||
if elapsed < 1.0 {
|
||||
return
|
||||
}
|
||||
|
||||
last := rb.lastBytes.Load()
|
||||
diff := total - last
|
||||
|
||||
bps := float64(diff) / elapsed
|
||||
|
||||
rb.bytesPerSec.Store(bps)
|
||||
rb.bitsPerSec.Store(bps * 8)
|
||||
|
||||
rb.lastTick.Store(now)
|
||||
rb.lastBytes.Store(total)
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) LastWriteTime() time.Time {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
|
||||
return rb.lastWrite
|
||||
return time.Unix(0, rb.lastWrite.Load())
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) GetLatest() (byte, bool) {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
@@ -91,6 +107,7 @@ func (rb *RingBuffer) GetLatest() (byte, bool) {
|
||||
return rb.data[idx], true
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) GetLast(n int) []byte {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
@@ -105,7 +122,6 @@ func (rb *RingBuffer) GetLast(n int) []byte {
|
||||
|
||||
if start < 0 {
|
||||
start += len(rb.data)
|
||||
|
||||
copy(res, rb.data[start:])
|
||||
copy(res[len(rb.data)-start:], rb.data[:rb.writePtr])
|
||||
} else {
|
||||
@@ -115,26 +131,32 @@ func (rb *RingBuffer) GetLast(n int) []byte {
|
||||
return res
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) IsAlive(timeout time.Duration) bool {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
|
||||
return time.Since(rb.lastWrite) < timeout
|
||||
return time.Since(time.Unix(0, rb.lastWrite.Load())) < timeout
|
||||
}
|
||||
|
||||
// =====================
|
||||
func (rb *RingBuffer) Stats() map[string]interface{} {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
filled := rb.count
|
||||
rb.mu.RUnlock()
|
||||
|
||||
bps, _ := rb.bytesPerSec.Load().(float64)
|
||||
bits, _ := rb.bitsPerSec.Load().(float64)
|
||||
|
||||
total := rb.totalBytes.Load()
|
||||
|
||||
return map[string]interface{}{
|
||||
"size": len(rb.data),
|
||||
"filled": rb.count,
|
||||
"last_write": rb.lastWrite,
|
||||
"size": len(rb.data),
|
||||
"filled": filled,
|
||||
|
||||
"total_bytes": rb.totalBytes,
|
||||
"total_bits": rb.totalBytes * 8,
|
||||
"last_write": time.Unix(0, rb.lastWrite.Load()),
|
||||
|
||||
"bytes_per_sec": rb.bytesPerSec,
|
||||
"bits_per_sec": rb.bitsPerSec,
|
||||
"total_bytes": total,
|
||||
"total_bits": total * 8,
|
||||
|
||||
"bytes_per_sec": bps,
|
||||
"bits_per_sec": bits,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user