f99010fae1
Desktop Artifacts / Desktop Build (Linux) (push) Waiting to run
Desktop Artifacts / Desktop Build (Windows) (push) Waiting to run
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Waiting to run
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
62 lines
2.0 KiB
Go
62 lines
2.0 KiB
Go
package sync
|
|
|
|
import (
|
|
"log"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// PhaseStats accumulates wall-clock time spent in each phase of the
|
|
// bulk-write hot path during a single sync pass. Each field is a
|
|
// nanosecond total. Fields are exported and read after the pass to keep
|
|
// the per-batch increment fast.
|
|
//
|
|
// The bulk path serializes a producer-consumer pipeline: worker
|
|
// goroutines parse files and the single collectAndBatch goroutine
|
|
// preps each result, scans for secrets, computes signals, and writes
|
|
// the batch. PhaseStats measures the time spent in each step of that
|
|
// consumer so a profile-driven analysis can attribute the wall clock.
|
|
type PhaseStats struct {
|
|
PrepNanos atomic.Int64 // prepareSessionWrite (toDBMessages, toDBSession, ...)
|
|
ScanNanos atomic.Int64 // computeSignalsAndSecrets (regex scan)
|
|
WriteNanos atomic.Int64 // db.WriteSessionBatch (one DB tx per batch)
|
|
Batches atomic.Int64
|
|
BatchedWrites atomic.Int64 // sessions written via bulk batches
|
|
WriteBatchSize atomic.Int64 // sum of len(writes) across all batches
|
|
}
|
|
|
|
// Reset zeroes every counter. Called at the start of each sync pass so
|
|
// stats reflect only that pass.
|
|
func (p *PhaseStats) Reset() {
|
|
p.PrepNanos.Store(0)
|
|
p.ScanNanos.Store(0)
|
|
p.WriteNanos.Store(0)
|
|
p.Batches.Store(0)
|
|
p.BatchedWrites.Store(0)
|
|
p.WriteBatchSize.Store(0)
|
|
}
|
|
|
|
// Log emits a single-line summary of accumulated phase totals. It is
|
|
// a no-op when no batch ran (so non-bulk syncs stay quiet).
|
|
func (p *PhaseStats) Log(label string) {
|
|
batches := p.Batches.Load()
|
|
if batches == 0 {
|
|
return
|
|
}
|
|
prep := time.Duration(p.PrepNanos.Load())
|
|
scan := time.Duration(p.ScanNanos.Load())
|
|
write := time.Duration(p.WriteNanos.Load())
|
|
avg := float64(p.WriteBatchSize.Load()) / float64(batches)
|
|
log.Printf(
|
|
"%s phase totals: prep=%s scan=%s write=%s "+
|
|
"batches=%d avg_batch=%.1f sessions_written=%d",
|
|
label,
|
|
prep.Round(time.Millisecond),
|
|
scan.Round(time.Millisecond),
|
|
write.Round(time.Millisecond),
|
|
batches,
|
|
avg,
|
|
p.BatchedWrites.Load(),
|
|
)
|
|
}
|