Summary (investigation — not a confirmed minimal repro)
While optimizing a protobuf encoder we saw large self-time in __v_boehm_collect_keepalive on -profile, and switching generated methods from by-value struct receivers (fn (m Msg)) to reference receivers (fn (m &Msg)) produced a measurable, repeatable encode speedup on large messages. The working theory was a per-iteration keepalive walk of the whole receiver inside loops over large fields, i.e. O(n²) behavior.
Filing this as an investigation, not a confirmed bug: minimal isolation attempts on V 0.5.2 5889122 did not reproduce quadratic behavior. Both a read-only sum loop and an allocating append loop over a by-value receiver with a large []u8 scale linearly and run at parity with (or faster than) the &-receiver version. So either the trigger needs a more specific shape than tested, or it has been improved upstream since first observed.
What did not reproduce it
struct Buf { data []u8 }
fn (s Buf) sum_byval() u64 { // vs fn (s &Buf)
mut acc := u64(0)
for i in 0 .. s.data.len { acc += s.data[i] }
return acc
}
byval/ref ratio ~1.0x across n = 1M/4M/16M; an allocating out << s.data[i] variant likewise linear.
What would confirm or close it
- The real trigger shape (candidates: by-value receiver whose method calls further methods on nested-struct fields, as generated protobuf
encode_to/encoded_size do; arrays of structs; specific GC mode).
- Or confirmation it is already fixed, in which case close.
Environment
V 0.5.2 5889122, Linux x86_64, -prod.
Note
The downstream code already uses & receivers everywhere, so this is not blocking anything — purely a tracking issue to either pin down or lay to rest.
Summary (investigation — not a confirmed minimal repro)
While optimizing a protobuf encoder we saw large self-time in
__v_boehm_collect_keepaliveon-profile, and switching generated methods from by-value struct receivers (fn (m Msg)) to reference receivers (fn (m &Msg)) produced a measurable, repeatable encode speedup on large messages. The working theory was a per-iteration keepalive walk of the whole receiver inside loops over large fields, i.e. O(n²) behavior.Filing this as an investigation, not a confirmed bug: minimal isolation attempts on
V 0.5.2 5889122did not reproduce quadratic behavior. Both a read-only sum loop and an allocating append loop over a by-value receiver with a large[]u8scale linearly and run at parity with (or faster than) the&-receiver version. So either the trigger needs a more specific shape than tested, or it has been improved upstream since first observed.What did not reproduce it
byval/ref ratio ~1.0x across n = 1M/4M/16M; an allocating
out << s.data[i]variant likewise linear.What would confirm or close it
encode_to/encoded_sizedo; arrays of structs; specific GC mode).Environment
V 0.5.2 5889122, Linux x86_64,-prod.Note
The downstream code already uses
&receivers everywhere, so this is not blocking anything — purely a tracking issue to either pin down or lay to rest.