Files
Nim/lib/std
Tomohiro 317bc10824 Makes containsOrIncl*[A](s: var PackedSet[A], key: A) proc faster (#25755)
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
```
2026-04-20 09:21:46 +08:00
..
2026-04-02 07:19:43 +02:00
2026-04-02 07:19:43 +02:00
2022-11-28 15:15:44 -05:00
2021-03-10 10:39:23 -08:00
2021-02-21 19:53:28 -08:00
2026-04-02 07:19:43 +02:00
2026-04-02 07:19:43 +02:00
2026-02-10 13:21:35 +01:00
2025-01-02 17:26:53 +01:00
2026-02-10 13:21:35 +01:00