Add MarshalTo for zero-allocation extension marshalling#344
Conversation
Add benchmarks for Marshal method on: - AbsSendTimeExtension - AbsCaptureTimeExtension (with and without offset) - AudioLevelExtension - TransportCCExtension - PlayoutDelayExtension - VLA
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #344 +/- ##
==========================================
+ Coverage 90.88% 90.97% +0.09%
==========================================
Files 27 27
Lines 2633 2716 +83
==========================================
+ Hits 2393 2471 +78
- Misses 168 171 +3
- Partials 72 74 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
e154dac to
2fa293f
Compare
| if len(buf) < absSendTimeExtensionSize { | ||
| return 0, io.ErrShortBuffer | ||
| } | ||
| buf[0] = byte(t.Timestamp & 0xFF0000 >> 16) |
There was a problem hiding this comment.
I think you can shift these directly, like buf[0] = t.Timestamp >> 16 and so on. Also the shifts will happen first in go, which causes this output to be incorrect (buf[0], buf[1], and buf[2] would all be the same value).
I'm wrong here, see explanation below
There was a problem hiding this comment.
in go & and >> are in the same precedence group, yeah it's a bit weird https://go.dev/ref/spec
There was a problem hiding this comment.
| // Marshal serializes the members to buffer. | ||
| func (t AbsSendTimeExtension) Marshal() ([]byte, error) { | ||
| return []byte{ | ||
| byte(t.Timestamp & 0xFF0000 >> 16), |
There was a problem hiding this comment.
Oh. This explains it 😅 I'm fairly certain that this doesn't do the right thing due to go's operator precedence since the shift happens first...
I'm wrong, see below
There was a problem hiding this comment.
This should be fine (in go), I can add parentheses to make it more clear.
In Go, & and >> are in the same precedence group, and they associate left-to-right.
There was a problem hiding this comment.
I think it's fine without parentheses. We'll have to update many old code if we want to add parentheses.
There was a problem hiding this comment.
I agree with @JoTurk. Also this and the above section can probably be handled in a separate pr.
|
@JoTurk let me know if you want me to revert the last change related with VLA extension (quite big diff) |
2fa293f to
b36759e
Compare
|
@thesyncim I'm sorry I'm confused what change to revert? We're fine with any change that doesn't break the API. Mind if you fix the lint? |
Add MarshalTo and MarshalSize methods to RTP header extensions. MarshalTo writes to a caller-provided buffer, returns io.ErrShortBuffer if too small. Allows zero-allocation marshaling when reusing buffers. Extensions updated: - AbsSendTimeExtension - AbsCaptureTimeExtension - AudioLevelExtension - TransportCCExtension - PlayoutDelayExtension
b36759e to
514c482
Compare
I believe you approved the PR before i pushed the last change that brings down VLA_MarshalTo to zero allocations. |
| func Leb128Size(in uint) int { | ||
| size := 1 | ||
| for in >>= 7; in != 0; in >>= 7 { | ||
| size++ | ||
| } | ||
|
|
||
| return size | ||
| } | ||
|
|
||
| // WriteLeb128To writes a LEB128 encoded value to buf and returns bytes written. | ||
| func WriteLeb128To(buf []byte, in uint) int { |
There was a problem hiding this comment.
Do you mind making the new leb128 helpers private for now? and inside VLA extension, I'm worried that it might confuse the library users. Also we'll have to think of an alloc-free API for the codec sub-package (It's on the todo list).
unless there is a reason for them to be public?
There was a problem hiding this comment.
nop, It just felt the right place to put them.
I will move them to vlaextension.go and make them private.
|
tagged in v1.8.27 |
Add MarshalTo and MarshalSize methods to RTP header extensions for zero-allocation marshaling to pre-allocated buffers. This avoids a few allocations per packet when setting multiple extensions.
Extensions updated:
Benchmarks