Skip to content

Release GVL during routing solves when no Ruby transit callbacks are registered#83

Open
erickreutz wants to merge 1 commit into
ankane:masterfrom
lugg:gvl-release
Open

Release GVL during routing solves when no Ruby transit callbacks are registered#83
erickreutz wants to merge 1 commit into
ankane:masterfrom
lugg:gvl-release

Conversation

@erickreutz

Copy link
Copy Markdown

Routing solves currently hold the GVL for their full duration, so in multi-threaded processes (Sidekiq, Puma) a solve with time_limit = 3 freezes every other Ruby thread for 3 seconds.

This releases the GVL around SolveWithParameters / SolveFromAssignmentWithParameters via rb_thread_call_without_gvl, but only when the model has no Ruby transit callbacks registered. Procs registered through register_transit_callback / register_unary_transit_callback are re-entered by the search constantly, so those models keep the GVL and behave exactly as today. Models built from register_transit_matrix / register_unary_transit_vector and the other native registrations never re-enter Ruby during the solve, so releasing is safe: input data is copied into the model at registration, and the returned Assignment* is model-owned and only read after the GVL is reacquired.

Implementation: the C++ bindings become _solve_with_parameters(params, release_gvl) and _solve_from_assignment_with_parameters(assignment, params, release_gvl); the Ruby side keeps the existing public API and passes release_gvl unless a Ruby callback was registered (the two callback registration methods set a flag and delegate to the renamed bindings, so keepAlive semantics are unchanged).

Tests: a background thread keeps running during a matrix-model solve (GVL released), callback models still solve correctly (GVL kept), matrix and callback models produce identical objectives, and solve_from_assignment_with_parameters gets the same coverage.

Ruby-proc transit callbacks re-enter Ruby mid-search, so the solve
bindings hold the GVL. Models built purely from transit matrices and
vectors never call back into Ruby; for those, wrap SolveWithParameters
and SolveFromAssignmentWithParameters in rb_thread_call_without_gvl so
long solves stop blocking every other thread in the process.

Tracking lives in RoutingModel Ruby wrappers: registering a Ruby
transit callback keeps solves on the GVL-holding path. Public API is
unchanged.
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