selector/

directory
v0.27.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: Apache-2.0

README

Token Selector

This package contains the token selector implementations. The token selector is responsible to select tokens of a given type and for a given amount from a wallet.

Available Implementations

  • Simple
  • Sherdlock (Default)

Benchmarking

go test -v -run=XXX -bench=BenchmarkSelectorSingle . -benchmem
go test -v -run=XXX -bench=BenchmarkSelectorParallel . -cpu=4,8,16,32,64,128,256,512 -benchmem

go test -ginkgo.v -ginkgo.trace .
Benchmarking against Postgres

BenchmarkSelectorPostgres (benchmark_postgres_test.go) runs the selectors against a real Postgres, built the way a node builds them: a generated core.yaml read by the FSC config provider, the multiplexed Postgres driver, the tokendb/tokenlockdb/ttxdb store service managers, and sherdlock.NewService / simple.NewService over a token.ManagementService.

make testing-docker-images                      # once: provides the postgres image
make benchmark-selector-postgres                # everything, 100 iterations per case
make benchmark-selector-postgres BENCH_FILTER='hot-wallet/' BENCH_TIME=500x
go test ./token/services/selector/ -run TestBenchPostgres -v   # check the harness itself

Without Docker the benchmark and the harness tests skip; with PANURUS_REQUIRE_POSTGRES set they fail instead. They also skip under -short.

Environment: PANURUS_SELECTOR_BENCH_MATRIX=full runs the full sherdlock cross product (fetcher x lock strategy x batch locking) in place of the one-axis sweep; PANURUS_SELECTOR_BENCH_LARGE=1 adds a 1M-token wallet to wallet-size; PANURUS_SELECTOR_BENCH_RETRY=5s sets token.selector.retryInterval for every case that does not name its own retry= segment (the benchmarks default to 20ms so contended cases do not spend their run asleep; 5s is the production default). Cases with an explicit retry= segment in their name (near-exhaustion, hot-wallet) ignore this variable: they sweep the retry-interval axis themselves with literals, so their label can never drift from what they actually ran at - set BENCH_FILTER='near-exhaustion/retry=5s' (or hot-wallet/retry=5s) to select the 5s arm directly instead; PANURUS_SELECTOR_BENCH_LOGSPEC overrides the package's default error-level logging (quieted so the per-request INFO/WARN logs a contended Select emits cannot interleave mid-line with benchmark result lines and corrupt them for benchstat - see TestMain in benchmark_postgres_setup_test.go), e.g. PANURUS_SELECTOR_BENCH_LOGSPEC=debug to see per-request detail while debugging a failure.

Each case reports selects/sec, p50-ms/p95-ms/p99-ms of Select alone, contended/op (requests that ended as locked or insufficient funds: expected under contention, not an error), lockRT/op (Postgres lock round trips) and uniqueViol/op, followed by the sherdlock metrics.

See docs/services/selector.md for the configurations and workloads.

Statistics with benchstat

A single run (BENCH_TIME's default -benchtime=100x) tells you a case's numbers; it does not tell you whether a difference between two cases is real or noise. BENCH_COUNT repeats every case that many times in one go test invocation, and benchstat turns the repeats into a median plus a confidence interval:

make benchmark-selector-postgres BENCH_FILTER='near-exhaustion/retry=(20ms|5s)/(sherdlock\+mixed.*|simple)' \
  BENCH_TIME=300x BENCH_COUNT=5 > near-exhaustion.txt
benchstat -col /retry near-exhaustion.txt

-col splits on whole /-separated name segments, not arbitrary substrings. A benchmark name's key=value segments (e.g. retry=20ms, hold=50ms) are each their own segment, so -col /retry can project them into columns of one comparison table. lockStrategy and maxConns, by contrast, live inside the +-joined blob pgConfig.name() produces (e.g. sherdlock+mixed+skipLocked+batch+clean+conns10) — they are not their own segment, so -col cannot reach them regardless of what key you pass it (including a positional key like -col /1: benchstat accepts those too, they just can't split a blob that isn't its own segment either). Renaming them into key=value segments would invalidate the existing case names across every workload, which this benchmark declines to do. Compare those two by filtering BENCH_FILTER to each value and reading the per-metric numbers by hand instead of reaching for -col on them.

Directories

Path Synopsis
mock
Code generated by counterfeiter.
Code generated by counterfeiter.
Package ratelimit provides an opt-in, built-in per-wallet rate limiter for token selection.
Package ratelimit provides an opt-in, built-in per-wallet rate limiter for token selection.
mocks
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL