XO0913: a slice in a loop read only by index or length
Reported by xo vet --cost. A slice of a Str or Bytes is a view (decision 0330), not free: each one checks its range (and, on a Str, a UTF-8 boundary), counts the text up and drops it. When the view is only indexed, measured or compared, read the whole text or bytes by offsets instead: std path’s match by offset went from 1.70x to 1.00x Go’s time (knowledgebase/std-performance-guide.md 4).
Example
fn count(s: Str, p: Str) -> Int {
var n = 0
var i = 0
while i + p.len() <= s.len() {
if s[i..i + p.len()] == p {
n += 1
}
i += 1
}
n
}Fix
fn count(s0: Str, p0: Str) -> Int {
let s = s0.bytes()
let p = p0.bytes()
var n = 0
var i = 0
while i + p.len() <= s.len() {
var k = 0
while k < p.len() && s[i + k] == p[k] {
k += 1
}
if k == p.len() {
n += 1
}
i += 1
}
n
}Run xo explain XO0913 for this text in a terminal, or see
section 10.6 of the specification.