mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-24 21:59:52 +00:00
This PR makes it faster when a number of elements is less than 34
I used following code to compare the speed of `containsOrIncl` proc.
It calls `isRecursiveStructuralType` proc defined in compiler/types.nim
that calls `containsOrIncl` with `IntSet`(= `PackedSet[int]`).
```nim
import std/[tables, monotimes, times, strformat]
import "$nim"/compiler/[astdef, ast, idents, types]
var idgen = IdGenerator(module: 0, symId: 0, typeId: 0, disambTable: initCountTable[PIdent]())
proc newType(kind: TTypeKind; son: sink PType = nil): PType =
result = newType(kind, idgen, nil, son)
proc genNoRecursPType(len: int): PType =
assert len > 1
let intTyp = newType(tyInt)
result = newType(tyRef, intTyp)
for i in 0..<(len - 2):
result = newType(tyRef, result)
proc test =
var noRecursPType = genNoRecursPType(4)
assert not isRecursiveStructuralType(noRecursPType)
test()
template measure(label: string; body: untyped): untyped =
let
loop = 2000
sampling = 200
block:
var r {.inject.} = false
var minT = initDuration(hours = 1)
for i in 0 ..< sampling:
let start = getMonoTime()
for j in 0 ..< loop:
body
let finish = getMonoTime()
minT = min(finish - start, minT)
echo ($r)[0], ' ', label, minT div loop
proc benchNoRecurs(len: int) =
echo fmt"No recursive: length: {len}"
var noRecursPType = genNoRecursPType(len)
measure("IntSet: "):
r = isRecursiveStructuralType(noRecursPType)
proc bench =
benchNoRecurs(30)
bench()
```
Output before changing code:
```
f IntSet: 1 microsecond and 262 nanoseconds
```
Output after change:
```
f IntSet: 833 nanoseconds
```
Why this PR make it faster:
```nim
proc containsOrIncl*[A](s: var PackedSet[A], key: A): bool =
...
if s.elems <= s.a.len:
for i in 0..<s.elems:
if s.a[i] == ord(key):
return true
# `incl` scans `s.a` again
incl(s, key)
result = false
```
```nim
proc containsOrIncl*[A](s: var PackedSet[A], key: A): bool =
...
if s.elems <= s.a.len:
for i in 0..<s.elems:
if s.a[i] == ord(key):
return true
if s.elems < s.a.len:
# put `key` in `s.a` instead of calling `incl(s, key)`
s.a[s.elems] = ord(key)
inc(s.elems)
else:
incl(s, key)
result = false
```