Boostrap without linking is (conservatively) 17% faster on my machine.
Test setup runs the compiler compiling itself under ORC in release mode
from a clean cache and no C compilation (`--compileOnly`.)
Multiple samples are gathered before judging a potential optimization.
The test suite passes locally before push and bootstrap is tested with
strict views (mostly as a sanity check).
Tests are fair in the sense that they compile the same git worktree and
produce identical C output.
Refc will see less or no benefit.
Changes:
- Save tree traversals in `considerGenSyms` when no mappings exist
- Inline `maybeSkipDistinct` into `typeRel` for a safe cursor
- Only skip to static when there is a static type to reach in
`paramTypesMatchAux`
- Disable overflow checks for hashes
- Disable bounds checks for `nextIdentIter`
- Use cursor annotation when judged safe
- Use lent annotation for ast accessors
Spiritual companion to #26084
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
```
* Improve documentation for packedsets
Add more runnableExamples
Add deprecated pragma to intsets
Replace intsets with packedsets in lib.rst
* Apply suggested changes
* Make IntSet an ordinal set OrdSet[A: Ordinal]
Backward compatibility with IntSet is maintained.
IntSet is an alias for OrdSet[int]
* move ordsets to new file, intsets exports it
* ordset, move to lib/std folder
* Fix `$` for ordsets and test cleanup
* Fix ordsets compilation in doc example
* Rename ordsets to packedsets