mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-25 06:18:16 +00:00
fixes #25718 This pull request optimizes sequence allocation in the Nim standard library by introducing a way to create uninitialized sequence payloads for element types that don't require zero-initialization. The changes allow for more efficient memory allocation when initializing sequences with types that have no references, avoiding unnecessary zeroing of memory. Sequence allocation and initialization improvements: * Added the `newSeqUninitRaw` procedure to create sequence payloads with a specified length without forcing zero-initialization for element types marked as `ntfNoRefs`. (`lib/system/sysstr.nim`, [lib/system/sysstr.nimR277-R292](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eR277-R292)) * Modified the `extendCapacityRaw` procedure and the `setLengthSeqImpl` template to use `newSeqUninitRaw` when zero-initialization is not required, controlled by the `doInit` static parameter. (`lib/system/sysstr.nim`, [[1]](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eR277-R292) [[2]](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eL316-R335)
This commit is contained in:
@@ -299,12 +299,22 @@ proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} =
|
||||
# since we steal the content from 's', it's crucial to set s's len to 0.
|
||||
s.len = 0
|
||||
|
||||
proc newSeqUninitRaw(typ: PNimType; len: int): pointer {.inline.} =
|
||||
## Creates a sequence payload with capacity and length `len` without
|
||||
## forcing zero-initialization for `ntfNoRefs` element types.
|
||||
result = nimNewSeqOfCap(typ, len)
|
||||
cast[PGenericSeq](result).len = len
|
||||
|
||||
proc extendCapacityRaw(src: PGenericSeq; typ: PNimType;
|
||||
elemSize, elemAlign, newLen: int): PGenericSeq {.inline.} =
|
||||
elemSize, elemAlign, newLen: int;
|
||||
doInit: static bool): PGenericSeq {.inline.} =
|
||||
## Reallocs `src` to fit `newLen` elements without any checks.
|
||||
## Capacity always increases to at least next `resize` step.
|
||||
let newCap = max(resize(src.space), newLen)
|
||||
result = cast[PGenericSeq](newSeq(typ, newCap))
|
||||
when doInit:
|
||||
result = cast[PGenericSeq](newSeq(typ, newCap))
|
||||
else:
|
||||
result = cast[PGenericSeq](newSeqUninitRaw(typ, newCap))
|
||||
copyMem(dataPointer(result, elemAlign), dataPointer(src, elemAlign), src.len * elemSize)
|
||||
# since we steal the content from 's', it's crucial to set s's len to 0.
|
||||
src.len = 0
|
||||
@@ -335,15 +345,19 @@ proc truncateRaw(src: PGenericSeq; baseFlags: set[TNimTypeFlag]; isTrivial: bool
|
||||
((result.len-%newLen) *% elemSize))
|
||||
|
||||
template setLengthSeqImpl(s: PGenericSeq, typ: PNimType, newLen: int; isTrivial: bool;
|
||||
doInit: static bool) =
|
||||
doInit: static bool) =
|
||||
if s == nil:
|
||||
if newLen == 0: return s
|
||||
else: return cast[PGenericSeq](newSeq(typ, newLen)) # newSeq zeroes!
|
||||
else:
|
||||
when doInit:
|
||||
return cast[PGenericSeq](newSeq(typ, newLen)) # newSeq zeroes!
|
||||
else:
|
||||
return cast[PGenericSeq](newSeqUninitRaw(typ, newLen))
|
||||
else:
|
||||
let elemSize = typ.base.size
|
||||
let elemAlign = typ.base.align
|
||||
result = if newLen > s.space:
|
||||
s.extendCapacityRaw(typ, elemSize, elemAlign, newLen)
|
||||
s.extendCapacityRaw(typ, elemSize, elemAlign, newLen, doInit)
|
||||
elif newLen < s.len:
|
||||
s.truncateRaw(typ.base.flags, isTrivial, elemSize, elemAlign, newLen)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user