Nim
Nim copied to clipboard
fixes #20232;indices now use `copyMem` and `moveMem`; much faster slicing and slicing assignments
fixes #20232
import benchy
template `^^`(s, i: untyped): untyped =
(when i is BackwardsIndex: s.len - int(i) else: int(i))
proc assign1*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) =
var a = s ^^ x.a
var xb = s ^^ x.b
var L = (xb) - a + 1
if L == b.len:
if L > 0:
if xb <= s.len:
when defined(nimSeqsV2):
prepareMutation(s)
copyMem(addr s[a], addr b[0], L)
else:
raise newException(IndexDefect, "defect")
proc assign2*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) =
var a = s ^^ x.a
var L = (s ^^ x.b) - a + 1
if L == b.len:
if L > 0:
for i in 0..<L: s[i+a] = b[i]
timeIt "copyMem":
var s = "abcdefgh"
for i in 0..1000000:
assign1(s, 1 .. 3, "xyz")
timeIt "old":
var s = "abcdefgh"
for i in 0..1000000:
assign2(s, 1 .. 3, "xyz")
A simple benchmark for string slice
-d:release
min time avg time std dv runs name
0.545 ms 0.603 ms ±0.017 x1000 copyMem
1.594 ms 1.754 ms ±0.256 x1000 old
-d:danger
0.541 ms 0.591 ms ±0.021 x1000 copyMem
0.932 ms 0.957 ms ±0.040 x1000 old
It uses moveMem
for array and seq slice assignment because there is a possibility that the memory overlaps using toOpenArray, for example. I don't see it is probable for strings, isn't it?