XO0907: a loop that copies a map's entries first
Reported by xo vet --cost, which builds the program and reads what the compiler did. A Map written while other values hold it (a store under a Mutex) is in log mode (decision 0291); a for over it walks its table in place when the table has no parent views and the body is small (at most 64 nodes) with no closure or defer. Otherwise the loop first copies every entry into fresh lists, counting each key and value up and down once per loop, atomically when the map is shared across threads. Keep the body small (call a function for the work), or read the entries once outside an outer loop.
Example
fn names(m: Mutex[Map[Int, Str]]) -> List[Str] {
m.with_read(fn(st) {
var out: List[Str] = []
for (_, n) in st {
out.push(n)
let f = fn() { n }
out.push(f())
}
out
})
}Fix
fn names(m: Mutex[Map[Int, Str]]) -> List[Str] {
m.with_read(fn(st) {
var out: List[Str] = []
for (_, n) in st {
out.push(n)
out.push(n)
}
out
})
}Run xo explain XO0907 for this text in a terminal, or see
section 10.6 of the specification.