Wow I love optimizing things. Most of the time is taken up but the float to
string conversion. I tried to eliminate all of the unnecessary copies, index
checks and buffer grows:
name ............................... min time avg time std dv runs
var str ........................... 11.591 ms 11.807 ms ±0.133 x423
orignal ........................... 12.601 ms 12.863 ms ±0.171 x388
Run
I only managed to eliminate 1ms, it's not worth the complexity, It's all in the
`c_sprintf`. Because you are dealing with graphics maybe there is a suboptimal
but a faster float writer. But still it will not be zero time it will always be
up to the float to string converter.
import vmath, benchy
var vecArr: seq[Vec3]
for i in 0 ..< 10000:
vecArr.add(vec3(i.float, i.float*2, 1))
{.push checks:off.}
proc c_sprintf(buf, fmt: cstring): int {.importc:"sprintf", header:
"<stdio.h>", varargs.}
proc addFloat32(s: var string, i: var int, f: float32) {.inline,.} =
i += c_sprintf(s[i].addr, "%f", f)
proc addChar(s: var string, i: var int, c: char) {.inline.} =
s[i] = c
inc i
timeIt "var str":
var
s = ""
i = 0
for j in 0 ..< vecArr.len:
s.setLen(i + 128)
let a = vecArr[j]
addChar(s, i, '<')
addFloat32(s, i, a.x)
addChar(s, i, ',')
addFloat32(s, i, a.y)
addChar(s, i, ',')
addFloat32(s, i, a.z)
addChar(s, i, '>')
s.setLen(i)
keep(s)
{.pop.}
# proc `$`*(x: float): string {.magic: "FloatToStr", noSideEffect.}
# ## The stringify operator for a float argument. Returns `x`
# ## converted to a decimal string.
# proc floatToStr(f: float64): string =
# var buffer: array[128, char]
# c_sprintf(addr buffer, "%.16e", f)
# result = ""
# for ch in buffer:
# if ch == '\0':
# return
# add(result, ch)
timeIt "orignal":
proc povVec3(a: Vec3): string {.inline.} =
"<" & $a.x & "," & $a.y & "," & $a.z & ">"
var vecStr = ""
for i in 0 ..< vecArr.len:
vecStr.add(povVec3(vecArr[i]))
keep(vecStr)
Run