From 317bc10824a8d5599b0b11c75d6248138b5dc302 Mon Sep 17 00:00:00 2001 From: Tomohiro Date: Mon, 20 Apr 2026 10:21:46 +0900 Subject: [PATCH] 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..