Sitelet https://github.com/bcrypt-ruby/bcrypt-ruby/pull/304
Skip to content

Allow fiber schedulers to offload bcrypt operations - #304

Open
samuel-williams-shopify wants to merge 2 commits into
bcrypt-ruby:masterfrom
samuel-williams-shopify:offload-safe
Open

samuel-williams-shopify wants to merge 2 commits into
bcrypt-ruby:masterfrom
samuel-williams-shopify:offload-safe

Conversation

@samuel-williams-shopify

Copy link
Copy Markdown

Bcrypt releases the GVL during salt generation and hashing, but these operations still block the calling fiber scheduler's thread. Mark both native callbacks with RB_NOGVL_OFFLOAD_SAFE so schedulers can execute them in a worker pool through blocking_operation_wait.

Both callbacks use frozen input strings and per-call output buffers, do not call Ruby APIs, and do not depend on the calling thread's state. The existing implementation remains the fallback when RB_NOGVL_OFFLOAD_SAFE is unavailable.

Includes regression specs for scheduler dispatch, known hash results, native failure results, and input lifetime and mutation during scheduler handoff. Also includes an Async benchmark, reproduction instructions, and all 30 measurement samples.

Benchmark

64 cost-10 hashes across eight Async tasks on an Apple M4 Pro, Ruby 4.0.7, Async 2.46.0, and io-event 1.22.1. Values are medians of five runs; timer delay is the median of each run's maximum delay for a 5 ms heartbeat.

Configuration Before After
Four workers: batch time 3.062 s 0.775 s
Four workers: hashes/second 20.9 82.6
Four workers: timer delay 378.98 ms 0.77 ms
One worker: hashes/second 20.9 20.8
One worker: timer delay 379.79 ms 1.63 ms

Four workers provide 3.95× throughput in this workload. One worker preserves throughput while keeping the event loop responsive. The unmodified extension submits zero operations to the pool; the modified extension offloads all 64 hashes per batch. Throughput remains similar with the pool disabled.

Validation

  • Ruby 4.0.7 and 3.4.4: 44 examples, 0 failures.
  • Ruby 3.3.1: 44 examples, 0 failures, 5 offload-specific examples skipped.
  • All five offload specs fail against the unmodified extension because its callbacks never reach the scheduler.
  • Every benchmark hash is checked against an expected result.

@samuel-williams-shopify

Copy link
Copy Markdown
Author

cc @ekmartin

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant