1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-18 18:40:22 +02:00

work-stealing optimization: stay with last-stolen worker

Previously we were always going round-robin.  Now a thief tries to
plunder its victim again directly.  Should result in less churn.
This commit is contained in:
Andy Wingo 2022-10-03 15:05:14 +02:00
parent 56aad402c9
commit 8b8ddaf6e2

View file

@ -485,17 +485,15 @@ tracer_can_steal_from_worker(struct tracer *tracer, size_t id) {
static struct gc_ref static struct gc_ref
trace_worker_steal_from_any(struct trace_worker *worker, struct tracer *tracer) { trace_worker_steal_from_any(struct trace_worker *worker, struct tracer *tracer) {
size_t steal_id = worker->steal_id;
for (size_t i = 0; i < tracer->worker_count; i++) { for (size_t i = 0; i < tracer->worker_count; i++) {
steal_id = (steal_id + 1) % tracer->worker_count; DEBUG("tracer #%zu: stealing from #%zu\n", worker->id, worker->steal_id);
DEBUG("tracer #%zu: stealing from #%zu\n", worker->id, steal_id); struct gc_ref obj = tracer_steal_from_worker(tracer, worker->steal_id);
struct gc_ref obj = tracer_steal_from_worker(tracer, steal_id);
if (gc_ref_is_heap_object(obj)) { if (gc_ref_is_heap_object(obj)) {
DEBUG("tracer #%zu: stealing got %p\n", worker->id, DEBUG("tracer #%zu: stealing got %p\n", worker->id,
gc_ref_heap_object(obj)); gc_ref_heap_object(obj));
worker->steal_id = steal_id;
return obj; return obj;
} }
worker->steal_id = (worker->steal_id + 1) % tracer->worker_count;
} }
DEBUG("tracer #%zu: failed to steal\n", worker->id); DEBUG("tracer #%zu: failed to steal\n", worker->id);
return gc_ref_null(); return gc_ref_null();
@ -503,16 +501,15 @@ trace_worker_steal_from_any(struct trace_worker *worker, struct tracer *tracer)
static int static int
trace_worker_can_steal_from_any(struct trace_worker *worker, struct tracer *tracer) { trace_worker_can_steal_from_any(struct trace_worker *worker, struct tracer *tracer) {
size_t steal_id = worker->steal_id;
DEBUG("tracer #%zu: checking if any worker has tasks\n", worker->id); DEBUG("tracer #%zu: checking if any worker has tasks\n", worker->id);
for (size_t i = 0; i < tracer->worker_count; i++) { for (size_t i = 0; i < tracer->worker_count; i++) {
steal_id = (steal_id + 1) % tracer->worker_count; int res = tracer_can_steal_from_worker(tracer, worker->steal_id);
int res = tracer_can_steal_from_worker(tracer, steal_id);
if (res) { if (res) {
DEBUG("tracer #%zu: worker #%zu has tasks!\n", worker->id, steal_id); DEBUG("tracer #%zu: worker #%zu has tasks!\n", worker->id,
worker->steal_id = steal_id; worker->steal_id);
return 1; return 1;
} }
worker->steal_id = (worker->steal_id + 1) % tracer->worker_count;
} }
DEBUG("tracer #%zu: nothing to steal\n", worker->id); DEBUG("tracer #%zu: nothing to steal\n", worker->id);
return 0; return 0;