XO0530: binding the payload of a field shares every heap field of a large value
Reported by xo vet, not xo check. match s.conn { Some(c) => ... } (or if let) on a field of a value that lives on binds a copy of the payload: every reference counted field of it (Str, Bytes, List, Map, handles) is shared, and released again when the copy or the field is dropped. For a payload with at least 8 such fields that is a fixed walk on every match, which profiles of the HTTP/2 server found at about 4,000 instructions a request. Test the field with .is_none() or a pattern without bindings first when the payload is not needed, read the one part needed (s.conn.map(...)), or take the value out of its owner before matching. See decision 0263.
Example
struct Conn {
a: Str, b: Str, c: Str, d: Str
e: Str, f: Str, g: Str, h: Str
}
struct Srv {
conn: Conn?
}
fn label(s: Srv) -> Str {
match s.conn {
Some(c) => c.a
None => "none"
}
}Fix
struct Conn {
a: Str, b: Str, c: Str, d: Str
e: Str, f: Str, g: Str, h: Str
}
struct Srv {
conn: Conn?
}
fn label(s: Srv) -> Str {
if s.conn.is_none() {
return "none"
}
s.conn.map(fn(c) { c.a }) ?? "none"
}Run xo explain XO0530 for this text in a terminal, or see
section 10.6 of the specification.