Skip to content

Latest commit

Β 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

README.md

πŸƒ @pokertools/bench

Performance benchmarks for poker hand evaluators

License: MIT

A benchmarking tool that compares @pokertools/evaluator against other popular poker hand evaluators to validate performance claims.


πŸ“‘ Table of Contents


πŸ“¦ Installation

The bench package is not published β€” it runs from source within the monorepo.

From Monorepo Root

npm run bench

From the Package Directory

cd packages/bench
npx ts-node index.ts

Note: ts-node is provided by the monorepo root devDependencies. The package uses "type": "commonjs" (CJS) and is not published β€” it runs from source via ts-node.


πŸ“Š Benchmark Results

Note: The results below are illustrative. Actual throughput depends on CPU speed, Node.js version, V8 JIT tier, memory speed, and system load. Run the benchmark on your own hardware for accurate measurements.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      BENCHMARK RESULTS (7-card hands)                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Library                    β”‚  Performance        β”‚  Input Type             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  πŸ₯‡ @pokertools/evaluator   β”‚  ~17M hands/sec     β”‚  Integer codes          β”‚
β”‚  πŸ₯ˆ phe                     β”‚  ~16M hands/sec     β”‚  Integer codes          β”‚
β”‚  πŸ₯‰ poker-evaluator         β”‚  ~1.3M hands/sec    β”‚  String arrays          β”‚
β”‚  πŸ₯‰ pokersolver             β”‚  ~70K hands/sec     β”‚  String arrays          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Performance comparison:

Library Speed vs @pokertools
@pokertools/evaluator 17M hands/sec baseline
phe 16M hands/sec ~1x
poker-evaluator 1.3M hands/sec ~13x slower
pokersolver 70K hands/sec ~240x slower

πŸš€ Running the Benchmark

From Monorepo Root

npm run bench

From Package Directory

cd packages/bench
npm run bench

Available Scripts

Script Command Description
bench ts-node index.ts Standard evaluator comparison benchmark (1,000 hands).
bench:load ts-node load.ts Short load test against a live API stack (health, queues, optional sockets/actions).
bench:soak BENCH_DURATION_MS=300000 BENCH_CONCURRENCY=32 ts-node load.ts Extended soak test (5 min, 32 concurrent workers).

Load/Soak Environment Variables

Variable Default Description
POKERTOOLS_API_BASE http://localhost:3000 PokerTools API base URL.
POKERTOOLS_WS_URL (derived from API_BASE) WebSocket endpoint for real-time benchmarks.
POKERTOOLS_TOKEN β€” JWT for authenticated WebSocket joins and actions.
POKERTOOLS_TABLE_ID β€” Table ID for game-action benchmarks.
REDIS_URL redis://localhost:6379 Redis URL for queue-depth benchmarks.
BENCH_DURATION_MS 30000 Duration of load test in ms (soak default: 300000).
BENCH_CONCURRENCY 16 Number of concurrent workers (soak default: 32).

Sample Output (Evaluator Benchmark)

Generating 1000 hands...
πŸ”₯ Warming up CPU and JIT...
----------------------------------------------------------------
phe (Int)                 |      16,574,257 hands/sec | Β±2.26%
poker-evaluator (Str)     |       1,375,495 hands/sec | Β±0.33%
pokersolver (Str)         |          70,980 hands/sec | Β±0.70%
@pokertools (Int)         |      17,915,292 hands/sec | Β±1.56%
----------------------------------------------------------------
πŸš€ WINNER: @pokertools (Int)

πŸ”§ How It Works

Test Setup

  1. Generates 1,000 random 7-card hands
  2. Warms up CPU and JIT compiler (5,000 iterations)
  3. Runs each evaluator on all hands per benchmark cycle
  4. Reports hands/second with statistical margin of error

Libraries Compared

Library Type Description
@pokertools/evaluator Integer Our evaluator using perfect hash tables
phe Integer Popular integer-based evaluator
poker-evaluator String Traditional string-based evaluator
pokersolver String Full-featured poker solver with comparison

πŸ“¦ Dependencies

{
  "@pokertools/evaluator": "1.0.16",
  "benchmark": "^2.1.4",
  "bullmq": "^5.79.2",
  "ws": "^8.21.0",
  "phe": "^0.6.0",
  "poker-evaluator": "^2.1.1",
  "pokersolver": "^2.1.4"
}

Note: ts-node is required to run the benchmark scripts and is provided by the monorepo root devDependencies. The package uses "type": "commonjs" (CJS) and is not published β€” it runs from source via ts-node.


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         BENCHMARK FLOW                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Generate Deck  β”‚  52 cards: ["2s", "3s", ..., "Ac"]
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Shuffle & Deal β”‚  1,000 random 7-card hands
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         β”‚                β”‚
    β–Ό         β–Ό                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚String β”‚ β”‚ Int   β”‚      β”‚  Int PHE  β”‚
β”‚Arrays β”‚ β”‚ Codes β”‚      β”‚  Format   β”‚
β””β”€β”€β”€β”¬β”€β”€β”€β”˜ β””β”€β”€β”€β”¬β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
    β”‚         β”‚                β”‚
    β”‚    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”           β”‚
    β”‚    β”‚         β”‚           β”‚
    β–Ό    β–Ό         β–Ό           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚poker-evalβ”‚ β”‚@pokertoolsβ”‚ β”‚   phe    β”‚
β”‚pokersolvrβ”‚ β”‚ evaluator β”‚ β”‚          β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚            β”‚            β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚ Benchmark.js   β”‚
         β”‚ Statistics     β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚  Results:      β”‚
         β”‚  hands/sec Β±%  β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”¬ Methodology

Why Integer-Based Evaluators Are Faster

String-based evaluation:
  "As" β†’ parse rank β†’ parse suit β†’ lookup β†’ evaluate

Integer-based evaluation:
  48 β†’ direct lookup β†’ evaluate

Overhead per card: ~10-20 nanoseconds for parsing
For 7 cards Γ— millions of hands = significant difference

JIT Warm-up

The benchmark includes a warm-up phase to ensure:

  • V8 JIT compiler has optimized hot paths
  • CPU frequency scaling has reached maximum
  • Garbage collection has stabilized

Statistical Validity

  • Benchmark.js runs multiple cycles automatically
  • Reports margin of error (Β±%) for each measurement
  • Runs until statistically significant results achieved

πŸ“ˆ Interpreting Results

What the Numbers Mean

  • hands/sec: Number of complete 7-card hand evaluations per second
  • Β±X%: Relative margin of error (95% confidence interval)

Factors Affecting Performance

Factor Impact
CPU Speed Linear correlation
Node.js Version V8 optimizations vary
Memory Speed Affects lookup table access
Other Processes Can cause variance

Fair Comparison Notes

  1. Integer vs String: Integer-based evaluators have an inherent advantage due to no parsing overhead
  2. Feature Set: pokersolver offers more features (hand comparison, wildcards) which adds overhead
  3. Memory Usage: Lookup table evaluators trade memory for speed

πŸ§ͺ Testing

The bench package has no test suite β€” it is the testing and benchmarking infrastructure for the monorepo. To verify it works correctly:

npm run bench -w @pokertools/bench
npm run bench:load -w @pokertools/bench

A passing run will output evaluator throughput statistics (hands/sec with margin of error) and load-test CSV results for CI ingestion.


πŸ“ˆ API, Worker, and Socket Load/Soak Benchmarks

Run short load checks against a live PokerTools stack:

# From the monorepo root:
POKERTOOLS_API_BASE=http://localhost:3000 npm run bench:load -w @pokertools/bench

To include authenticated WebSocket joins and game actions, provide a JWT and table ID:

POKERTOOLS_TOKEN=<jwt> POKERTOOLS_TABLE_ID=<table-id> \
  npm run bench:load -w @pokertools/bench

Longer soak profile (5 minutes, 32 workers):

npm run bench:soak -w @pokertools/bench

Results are emitted as CSV (name,count,ok,failed,p50_ms,p95_ms,max_ms) for CI ingestion.


πŸ”— Related Packages

Package Description
@pokertools/evaluator The evaluator being benchmarked
@pokertools/engine Uses the evaluator for showdown

πŸ“„ License

MIT Β© A.Aurelius