Files
2026-07-13 13:17:40 +08:00

109 lines
2.9 KiB
Python

import json
import os
import threading
import time
import numpy as np
import ray
import ray._private.worker
NUM_WORKERS = 10
OBJECT_SIZE = 1024 * 1024 # 1 MiB, above the 100 KB inlining threshold
@ray.remote(num_cpus=1)
def produce_block():
return np.zeros(OBJECT_SIZE, dtype=np.uint8)
@ray.remote(num_cpus=1)
def consume_block(block_ref):
return len(block_ref)
def test_callback_pipeline(num_blocks, timeout_s=60):
core_worker = ray._private.worker.global_worker.core_worker
latencies = []
drop_times = {}
lock = threading.Lock()
done = threading.Event()
def on_freed(id_bytes):
with lock:
latencies.append(time.perf_counter() - drop_times[id_bytes])
if len(latencies) == num_blocks:
done.set()
refs = [
produce_block.options(scheduling_strategy="SPREAD").remote()
for _ in range(num_blocks)
]
ray.wait(refs, num_returns=len(refs))
# live_refs keeps each block ref alive until its consumer completes.
live_refs = {}
for ref in refs:
assert core_worker.add_object_out_of_scope_callback(ref, on_freed)
consumer = consume_block.remote(ref)
live_refs[consumer] = ref
del refs
# Release each ref as its consumer completes.
pending = list(live_refs.keys())
while pending:
done_list, pending = ray.wait(pending, num_returns=1)
for consumer in done_list:
ref = live_refs.pop(consumer)
drop_times[ref.binary()] = time.perf_counter()
del ref
if not done.wait(timeout=timeout_s):
raise TimeoutError(
f"Only {len(latencies)}/{num_blocks} callbacks fired within {timeout_s}s"
)
latencies.sort()
p95 = latencies[int(len(latencies) * 0.95)]
print(f" {num_blocks} blocks: p95={p95:.4f}s")
return p95
ray.init(address="auto")
# Warm up gRPC connections and worker pools.
ray.get(
[
produce_block.options(scheduling_strategy="SPREAD").remote()
for _ in range(NUM_WORKERS)
]
)
p95_100 = test_callback_pipeline(100)
p95_1k = test_callback_pipeline(1000)
print("\nSummary:")
print(f" 100 blocks: p95={p95_100:.4f}s")
print(f" 1k blocks: p95={p95_1k:.4f}s")
if "TEST_OUTPUT_JSON" in os.environ:
with open(os.environ["TEST_OUTPUT_JSON"], "w") as out_file:
results = {
"p95_100": p95_100,
"p95_1k": p95_1k,
"perf_metrics": [
{
"perf_metric_name": "callback_p95_latency_100_blocks_s",
"perf_metric_value": p95_100,
"perf_metric_type": "LATENCY",
},
{
"perf_metric_name": "callback_p95_latency_1k_blocks_s",
"perf_metric_value": p95_1k,
"perf_metric_type": "LATENCY",
},
],
}
json.dump(results, out_file)