# 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

```xo
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

```xo
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](../../spec/core/#106-diagnostic-codes).

