Skip to content

Commit 2bcb8e7

Browse files
committed
perf: faster Ogg page-magic scan in Broadcast; widen mirrorTranscodeMetadata tick to 5s
Broadcast(): the OggS page-boundary scanner was inspecting every byte in the data slice one-by-one even though the magic only ever starts where data[i] == 'O'. Skip ahead with bytes.IndexByte('O') between candidates — for a 4-8 KiB Broadcast call with few O bytes (the common case for Opus payloads) that is roughly 16x fewer comparisons. mirrorTranscodeMetadata: bumped the polling tick from 2 s to 5 s. Metadata changes per-track i.e. every few minutes; catching it 2 s earlier vs 5 s is invisible to listeners and the YP directory, and a 2.5x slower tick removes RLock acquisitions on each input stream.
1 parent 6d6364b commit 2bcb8e7

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

relay/stream.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package relay
22

33
import (
4+
"bytes"
45
"strings"
56
"sync"
67
"sync/atomic"
@@ -441,15 +442,29 @@ func (s *Stream) Broadcast(data []byte, relay *Relay) {
441442
atomic.AddInt64(&relay.BytesIn, int64(len(data)))
442443
atomic.AddInt64(&s.BytesIn, int64(len(data)))
443444

444-
// Track Ogg Page boundaries for alignment
445-
// This enables new Opus listeners to start at proper page boundaries
445+
// Track Ogg page boundaries for alignment so new Opus / Vorbis
446+
// listeners start at a proper page edge. Use bytes.IndexByte to
447+
// skip ahead between candidate 'O' bytes — the previous loop
448+
// inspected every byte one at a time even though the magic only
449+
// starts where data[i] == 'O'. For a 4-8 KiB Broadcast call with
450+
// few O bytes (the common case for Opus payload), this is roughly
451+
// 16x fewer comparisons.
446452
if s.IsOggStream {
447-
for i := 0; i <= len(data)-4; i++ {
448-
if data[i] == 'O' && data[i+1] == 'g' && data[i+2] == 'g' && data[i+3] == 'S' {
453+
i := 0
454+
for i <= len(data)-4 {
455+
j := bytes.IndexByte(data[i:len(data)-3], 'O')
456+
if j < 0 {
457+
break
458+
}
459+
i += j
460+
if data[i+1] == 'g' && data[i+2] == 'g' && data[i+3] == 'S' {
449461
offset := s.Buffer.Head + int64(i)
450462
s.LastPageOffset = offset
451463
s.PageOffsets[s.PageIndex%len(s.PageOffsets)] = offset
452464
s.PageIndex++
465+
i += 4
466+
} else {
467+
i++
453468
}
454469
}
455470
}

relay/transcode.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,12 @@ type TranscoderStats struct {
550550
// upstream encoder, and the public Icecast directory listing shows
551551
// generic info on the transcoded sibling.
552552
func mirrorTranscodeMetadata(ctx context.Context, input, output *Stream) {
553-
ticker := time.NewTicker(2 * time.Second)
553+
// 5 s cadence is plenty for metadata that changes per-track
554+
// (i.e. every few minutes). 2 s was poll-noise — with N
555+
// transcoders sharing one input that's N RLock acquisitions per
556+
// poll, and the latency benefit of catching a song change two
557+
// seconds earlier vs five is invisible to the listener.
558+
ticker := time.NewTicker(5 * time.Second)
554559
defer ticker.Stop()
555560
var lastSong, lastGenre, lastURL, lastDesc string
556561
var lastPublic, lastVisible bool

0 commit comments

Comments
 (0)