Skip to content

perf: random Choice allocates twice per drawn element (200 013 allocations for 100 000 draws) #103

Open

Description

@tannevaled

Generator.Choice, RandomState.Choice and random.Choice allocate twice per drawn element, so they cannot be as fast as numpy.random.Generator.choice, which draws the indices and gathers them in one vectorised pass.

Witness (allocation counts, exact under any load; clone at c7b9263, bench/ of the W3 refbench PR)

go test -run TestPerf -perf.record -cpu 1 (GOMAXPROCS=1), size = 100000 draws from a 1000-element array:

row allocs per call
random.Generator.Choice (array a) 200013
random.RandomState.Choice 200012
random.Choice 200012
random.Generator.ChoiceN (integer n, no gather) 8

ChoiceN draws the same indices through choiceIndices and costs 8 allocations; the 200 000 extra are in the gather: Choice (random/generator.go:756-773) ends in takeAxis(a, idx, size, ax), and the count is 2 x size (the other 13 are fixed). NumPy: 1 allocation (the result).

To do

  • Make the gather of Choice allocation-free per element (one result array); the allocation count of the three rows above must drop to a small constant. The row inventory and counts are recorded in docs/perf.json, so the PR that fixes it must record the decrease.
  • Timing is deferred (1-minute load was 8 to 80 when this was filed); this issue is filed on the allocation witness alone, as the campaign rules allow.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions