mirror of
https://github.com/livekit/livekit.git
synced 2026-10-09 11:37:56 +00:00
* Reduce descriptor marshal allocations on Go 1.26.4/linux-amd64 Signed-off-by: Perfloop Agent <agent@perfloop.ai> * Use require in the descriptor marshal benchmark test Signed-off-by: Perfloop Agent <agent@perfloop.ai> * sfu: marshal dependency descriptors into caller-owned scratch * sfu: reuse the selector's descriptor clone * sfu: share one inline header-extension size constant --------- Signed-off-by: Perfloop Agent <agent@perfloop.ai>
110 lines
3.3 KiB
Go
110 lines
3.3 KiB
Go
// Copyright 2026 LiveKit, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package pacer
|
|
|
|
import (
|
|
"bytes"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/pion/rtp"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/livekit/protocol/logger"
|
|
|
|
"github.com/livekit/livekit-server/pkg/sfu/bwe"
|
|
dd "github.com/livekit/livekit-server/pkg/sfu/rtpextension/dependencydescriptor"
|
|
"github.com/livekit/livekit-server/pkg/sfu/utils"
|
|
)
|
|
|
|
// bwe.NullBWE is meant to be embedded and lacks Type
|
|
type nullBWE struct{ *bwe.NullBWE }
|
|
|
|
func (nullBWE) Type() bwe.BWEType { return bwe.BWETypeNone }
|
|
|
|
// records extension sizes without allocating so AllocsPerRun measures only SendPacket
|
|
type extCheckWriter struct {
|
|
writes int
|
|
absSendTimeLen int
|
|
transportWideLen int
|
|
}
|
|
|
|
func (w *extCheckWriter) WriteRTP(header *rtp.Header, _ []byte) (int, error) {
|
|
w.writes++
|
|
w.absSendTimeLen += len(header.GetExtension(1))
|
|
w.transportWideLen += len(header.GetExtension(2))
|
|
return 0, nil
|
|
}
|
|
|
|
func (w *extCheckWriter) Write(_ []byte) (int, error) { return 0, nil }
|
|
|
|
// SendPacket patches abs-send-time and transport-cc into a pooled header,
|
|
// this must not allocate per packet
|
|
func TestSendPacketHeaderExtensionsNoAlloc(t *testing.T) {
|
|
b := NewBase(logger.GetLogger(), nullBWE{&bwe.NullBWE{}})
|
|
headerPool := &sync.Pool{New: func() any { return &rtp.Header{} }}
|
|
w := &extCheckWriter{}
|
|
payload := make([]byte, 100)
|
|
|
|
send := func() {
|
|
hdr := headerPool.Get().(*rtp.Header)
|
|
exts := hdr.Extensions[:0]
|
|
*hdr = rtp.Header{Version: 2, SequenceNumber: 1, Timestamp: 2, SSRC: 3}
|
|
hdr.Extensions = exts
|
|
|
|
p := PacketFactory.Get().(*Packet)
|
|
*p = Packet{
|
|
Header: hdr,
|
|
HeaderPool: headerPool,
|
|
HeaderSize: hdr.MarshalSize(),
|
|
Payload: payload,
|
|
AbsSendTimeExtID: 1,
|
|
TransportWideExtID: 2,
|
|
WriteStream: w,
|
|
}
|
|
_, err := b.SendPacket(p)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
send() // warm the pools; AllocsPerRun also runs once before measuring
|
|
allocs := testing.AllocsPerRun(1000, send)
|
|
require.Equal(t, 1002, w.writes)
|
|
require.Equal(t, 3*w.writes, w.absSendTimeLen)
|
|
require.Equal(t, 2*w.writes, w.transportWideLen)
|
|
if !utils.RaceEnabled {
|
|
require.Equal(t, 0.0, allocs, "allocations per SendPacket")
|
|
}
|
|
}
|
|
|
|
func TestHoldExtension(t *testing.T) {
|
|
p := &Packet{}
|
|
|
|
ext := []byte{1, 2, 3}
|
|
held := p.HoldExtension(ext)
|
|
require.Equal(t, ext, held)
|
|
require.Same(t, &p.extBuf[0], &held[0], "the extension has to be held in the packet's scratch")
|
|
|
|
ext[0] = 9
|
|
require.EqualValues(t, 1, held[0], "the held copy has to be independent of the caller's slice")
|
|
|
|
// exactly the one byte extension profile payload cap
|
|
exact := bytes.Repeat([]byte{7}, dd.MaxInlineExtensionSize)
|
|
held = p.HoldExtension(exact)
|
|
require.Equal(t, exact, held)
|
|
|
|
// one byte more does not fit
|
|
require.Nil(t, p.HoldExtension(bytes.Repeat([]byte{7}, dd.MaxInlineExtensionSize+1)))
|
|
}
|