Skip to content

Commit 077af8e

Browse files
barbashovIlya Barbashov
andauthored
Performance optimization: using NextBytesNoCopy where possible (#17)
* Performance optimization: using NextBytesFast where possible * follow up * BenchmarkDemuxer_NextData added * NextBytesFast -> NextBytesNoCopy Co-authored-by: Ilya Barbashov <[email protected]>
1 parent df3794c commit 077af8e

19 files changed

+191
-42
lines changed

data_eit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func parseEITSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
3636

3737
// Get next 2 bytes
3838
var bs []byte
39-
if bs, err = i.NextBytes(2); err != nil {
39+
if bs, err = i.NextBytesNoCopy(2); err != nil {
4040
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
4141
return
4242
}
@@ -45,7 +45,7 @@ func parseEITSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
4545
d.TransportStreamID = uint16(bs[0])<<8 | uint16(bs[1])
4646

4747
// Get next 2 bytes
48-
if bs, err = i.NextBytes(2); err != nil {
48+
if bs, err = i.NextBytesNoCopy(2); err != nil {
4949
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
5050
return
5151
}
@@ -75,7 +75,7 @@ func parseEITSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
7575
// Loop until end of section data is reached
7676
for i.Offset() < offsetSectionsEnd {
7777
// Get next 2 bytes
78-
if bs, err = i.NextBytes(2); err != nil {
78+
if bs, err = i.NextBytesNoCopy(2); err != nil {
7979
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
8080
return
8181
}

data_nit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func parseNITSection(i *astikit.BytesIterator, tableIDExtension uint16) (d *NITD
3535

3636
// Get next bytes
3737
var bs []byte
38-
if bs, err = i.NextBytes(2); err != nil {
38+
if bs, err = i.NextBytesNoCopy(2); err != nil {
3939
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
4040
return
4141
}
@@ -50,7 +50,7 @@ func parseNITSection(i *astikit.BytesIterator, tableIDExtension uint16) (d *NITD
5050
ts := &NITDataTransportStream{}
5151

5252
// Get next bytes
53-
if bs, err = i.NextBytes(2); err != nil {
53+
if bs, err = i.NextBytesNoCopy(2); err != nil {
5454
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
5555
return
5656
}
@@ -59,7 +59,7 @@ func parseNITSection(i *astikit.BytesIterator, tableIDExtension uint16) (d *NITD
5959
ts.TransportStreamID = uint16(bs[0])<<8 | uint16(bs[1])
6060

6161
// Get next bytes
62-
if bs, err = i.NextBytes(2); err != nil {
62+
if bs, err = i.NextBytesNoCopy(2); err != nil {
6363
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
6464
return
6565
}

data_pat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func parsePATSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
3232
for i.Offset() < offsetSectionsEnd {
3333
// Get next bytes
3434
var bs []byte
35-
if bs, err = i.NextBytes(4); err != nil {
35+
if bs, err = i.NextBytesNoCopy(4); err != nil {
3636
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
3737
return
3838
}

data_pat_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestParsePATSection(t *testing.T) {
3535
assert.NoError(t, err)
3636
}
3737

38-
func TestWritePatSection(t *testing.T) {
38+
func TestWritePATSection(t *testing.T) {
3939
bw := &bytes.Buffer{}
4040
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: bw})
4141
n, err := writePATSection(w, pat)
@@ -44,3 +44,25 @@ func TestWritePatSection(t *testing.T) {
4444
assert.Equal(t, n, bw.Len())
4545
assert.Equal(t, patBytes(), bw.Bytes())
4646
}
47+
48+
func BenchmarkParsePATSection(b *testing.B) {
49+
b.ReportAllocs()
50+
bs := patBytes()
51+
52+
for i := 0; i < b.N; i++ {
53+
parsePATSection(astikit.NewBytesIterator(bs), len(bs), uint16(1))
54+
}
55+
}
56+
57+
func BenchmarkWritePATSection(b *testing.B) {
58+
b.ReportAllocs()
59+
60+
bw := &bytes.Buffer{}
61+
bw.Grow(1024)
62+
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: bw})
63+
64+
for i := 0; i < b.N; i++ {
65+
bw.Reset()
66+
writePATSection(w, pat)
67+
}
68+
}

data_pes.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func parsePESHeader(i *astikit.BytesIterator) (h *PESHeader, dataStart, dataEnd
162162

163163
// Get next bytes
164164
var bs []byte
165-
if bs, err = i.NextBytes(2); err != nil {
165+
if bs, err = i.NextBytesNoCopy(2); err != nil {
166166
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
167167
return
168168
}
@@ -276,7 +276,7 @@ func parsePESOptionalHeader(i *astikit.BytesIterator) (h *PESOptionalHeader, dat
276276
// ES rate
277277
if h.HasESRate {
278278
var bs []byte
279-
if bs, err = i.NextBytes(3); err != nil {
279+
if bs, err = i.NextBytesNoCopy(3); err != nil {
280280
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
281281
return
282282
}
@@ -304,7 +304,7 @@ func parsePESOptionalHeader(i *astikit.BytesIterator) (h *PESOptionalHeader, dat
304304
// CRC
305305
if h.HasCRC {
306306
var bs []byte
307-
if bs, err = i.NextBytes(2); err != nil {
307+
if bs, err = i.NextBytesNoCopy(2); err != nil {
308308
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
309309
return
310310
}
@@ -347,7 +347,7 @@ func parsePESOptionalHeader(i *astikit.BytesIterator) (h *PESOptionalHeader, dat
347347
// Program packet sequence counter
348348
if h.HasProgramPacketSequenceCounter {
349349
var bs []byte
350-
if bs, err = i.NextBytes(2); err != nil {
350+
if bs, err = i.NextBytesNoCopy(2); err != nil {
351351
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
352352
return
353353
}
@@ -359,7 +359,7 @@ func parsePESOptionalHeader(i *astikit.BytesIterator) (h *PESOptionalHeader, dat
359359
// P-STD buffer
360360
if h.HasPSTDBuffer {
361361
var bs []byte
362-
if bs, err = i.NextBytes(2); err != nil {
362+
if bs, err = i.NextBytesNoCopy(2); err != nil {
363363
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
364364
return
365365
}
@@ -405,7 +405,7 @@ func parseDSMTrickMode(i byte) (m *DSMTrickMode) {
405405
// parsePTSOrDTS parses a PTS or a DTS
406406
func parsePTSOrDTS(i *astikit.BytesIterator) (cr *ClockReference, err error) {
407407
var bs []byte
408-
if bs, err = i.NextBytes(5); err != nil {
408+
if bs, err = i.NextBytesNoCopy(5); err != nil {
409409
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
410410
return
411411
}
@@ -416,7 +416,7 @@ func parsePTSOrDTS(i *astikit.BytesIterator) (cr *ClockReference, err error) {
416416
// parseESCR parses an ESCR
417417
func parseESCR(i *astikit.BytesIterator) (cr *ClockReference, err error) {
418418
var bs []byte
419-
if bs, err = i.NextBytes(6); err != nil {
419+
if bs, err = i.NextBytesNoCopy(6); err != nil {
420420
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
421421
return
422422
}

data_pes_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,3 +485,25 @@ func TestWritePESOptionalHeader(t *testing.T) {
485485
})
486486
}
487487
}
488+
489+
func BenchmarkParsePESData(b *testing.B) {
490+
bss := make([][]byte, len(pesTestCases))
491+
492+
for ti, tc := range pesTestCases {
493+
buf := bytes.Buffer{}
494+
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: &buf})
495+
tc.headerBytesFunc(w, true, true)
496+
tc.optionalHeaderBytesFunc(w, true, true)
497+
tc.bytesFunc(w, true, true)
498+
bss[ti] = buf.Bytes()
499+
}
500+
501+
for ti, tc := range pesTestCases {
502+
b.Run(tc.name, func(b *testing.B) {
503+
b.ReportAllocs()
504+
for i := 0; i < b.N; i++ {
505+
parsePESData(astikit.NewBytesIterator(bss[ti]))
506+
}
507+
})
508+
}
509+
}

data_pmt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func parsePMTSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
5858

5959
// Get next bytes
6060
var bs []byte
61-
if bs, err = i.NextBytes(2); err != nil {
61+
if bs, err = i.NextBytesNoCopy(2); err != nil {
6262
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
6363
return
6464
}
@@ -88,7 +88,7 @@ func parsePMTSection(i *astikit.BytesIterator, offsetSectionsEnd int, tableIDExt
8888
e.StreamType = StreamType(b)
8989

9090
// Get next bytes
91-
if bs, err = i.NextBytes(2); err != nil {
91+
if bs, err = i.NextBytesNoCopy(2); err != nil {
9292
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
9393
return
9494
}

data_pmt_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,25 @@ func TestWritePMTSection(t *testing.T) {
4949
assert.Equal(t, n, buf.Len())
5050
assert.Equal(t, pmtBytes(), buf.Bytes())
5151
}
52+
53+
func BenchmarkParsePMTSection(b *testing.B) {
54+
b.ReportAllocs()
55+
bs := pmtBytes()
56+
57+
for i := 0; i < b.N; i++ {
58+
parsePMTSection(astikit.NewBytesIterator(bs), len(bs), uint16(1))
59+
}
60+
}
61+
62+
func BenchmarkWritePMTSection(b *testing.B) {
63+
b.ReportAllocs()
64+
65+
bw := &bytes.Buffer{}
66+
bw.Grow(1024)
67+
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: bw})
68+
69+
for i := 0; i < b.N; i++ {
70+
bw.Reset()
71+
writePMTSection(w, pmt)
72+
}
73+
}

data_psi.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func parsePSISection(i *astikit.BytesIterator) (s *PSISection, stop bool, err er
165165
// Get CRC32 data
166166
i.Seek(offsetStart)
167167
var crc32Data []byte
168-
if crc32Data, err = i.NextBytes(offsetSectionsEnd - offsetStart); err != nil {
168+
if crc32Data, err = i.NextBytesNoCopy(offsetSectionsEnd - offsetStart); err != nil {
169169
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
170170
return
171171
}
@@ -189,7 +189,7 @@ func parsePSISection(i *astikit.BytesIterator) (s *PSISection, stop bool, err er
189189
// parseCRC32 parses a CRC32
190190
func parseCRC32(i *astikit.BytesIterator) (c uint32, err error) {
191191
var bs []byte
192-
if bs, err = i.NextBytes(4); err != nil {
192+
if bs, err = i.NextBytesNoCopy(4); err != nil {
193193
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
194194
return
195195
}
@@ -229,7 +229,7 @@ func parsePSISectionHeader(i *astikit.BytesIterator) (h *PSISectionHeader, offse
229229

230230
// Get next bytes
231231
var bs []byte
232-
if bs, err = i.NextBytes(2); err != nil {
232+
if bs, err = i.NextBytesNoCopy(2); err != nil {
233233
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
234234
return
235235
}
@@ -358,7 +358,7 @@ func parsePSISectionSyntaxHeader(i *astikit.BytesIterator) (h *PSISectionSyntaxH
358358

359359
// Get next 2 bytes
360360
var bs []byte
361-
if bs, err = i.NextBytes(2); err != nil {
361+
if bs, err = i.NextBytesNoCopy(2); err != nil {
362362
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
363363
return
364364
}

data_psi_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,10 @@ func TestWritePSIData(t *testing.T) {
374374
})
375375
}
376376
}
377+
378+
func BenchmarkParsePSIData(b *testing.B) {
379+
b.ReportAllocs()
380+
for i := 0; i < b.N; i++ {
381+
parsePSIData(astikit.NewBytesIterator(psiBytes()))
382+
}
383+
}

0 commit comments

Comments
 (0)