|
14 | 14 | from ray._common.test_utils import wait_for_condition |
15 | 15 | from ray._private.gc_collect_manager import PythonGCThread |
16 | 16 | from ray._private.internal_api import global_gc |
17 | | -from ray._private.ray_constants import RAY_GC_MIN_COLLECT_INTERVAL |
18 | 17 |
|
19 | 18 | logger = logging.getLogger(__name__) |
20 | 19 |
|
@@ -248,107 +247,69 @@ def make_garbage(self): |
248 | 247 | def has_garbage(self): |
249 | 248 | return self.garbage() is not None |
250 | 249 |
|
251 | | - try: |
252 | | - gc.disable() |
253 | | - |
254 | | - # 1) Test GC behavior for the local driver. |
255 | | - |
256 | | - # 1a) Wait for the first GC to happen to avoid timing issues. |
257 | | - local_ref = weakref.ref(ObjectWithCyclicRef()) |
258 | | - wait_for_condition(lambda: local_ref() is None, retry_interval_ms=10) |
| 250 | + gc.disable() |
259 | 251 |
|
260 | | - # 1b) Check that GC *is not* called within the min interval. |
261 | | - local_ref = weakref.ref(ObjectWithCyclicRef()) |
262 | | - time.sleep(RAY_GC_MIN_COLLECT_INTERVAL / 2) |
263 | | - assert local_ref() is not None |
| 252 | + # 1) Test GC behavior for the local driver. |
264 | 253 |
|
265 | | - # 1c) Check that GC *is* called after the min interval. |
266 | | - wait_for_condition( |
267 | | - lambda: local_ref() is None, |
268 | | - timeout=RAY_GC_MIN_COLLECT_INTERVAL * 2, |
269 | | - ) |
| 254 | + # 1a) Wait for the first GC to happen to avoid timing issues. |
| 255 | + local_ref = weakref.ref(ObjectWithCyclicRef()) |
| 256 | + wait_for_condition(lambda: local_ref() is None, retry_interval_ms=10) |
270 | 257 |
|
271 | | - # 2) Test GC behavior for a remote actor. |
272 | | - a = GarbageHolder.remote() |
| 258 | + # 1b) Check that GC is called. |
| 259 | + wait_for_condition( |
| 260 | + lambda: local_ref() is None, |
| 261 | + timeout=5, |
| 262 | + ) |
273 | 263 |
|
274 | | - # 2a) Wait for the first GC to happen to avoid timing issues. |
275 | | - ray.get(a.make_garbage.remote()) |
276 | | - wait_for_condition( |
277 | | - lambda: not ray.get(a.has_garbage.remote()), retry_interval_ms=10 |
278 | | - ) |
| 264 | + # 2) Test GC behavior for a remote actor. |
| 265 | + a = GarbageHolder.remote() |
279 | 266 |
|
280 | | - # 2b) Check that GC *is not* called within the min interval. |
281 | | - ray.get(a.make_garbage.remote()) |
282 | | - time.sleep(RAY_GC_MIN_COLLECT_INTERVAL / 2) |
283 | | - assert ray.get(a.has_garbage.remote()) |
| 267 | + # 2a) Wait for the first GC to happen to avoid timing issues. |
| 268 | + ray.get(a.make_garbage.remote()) |
| 269 | + wait_for_condition( |
| 270 | + lambda: not ray.get(a.has_garbage.remote()), retry_interval_ms=10 |
| 271 | + ) |
284 | 272 |
|
285 | | - # 2c) Check that GC *is* called after the min interval. |
286 | | - wait_for_condition( |
287 | | - lambda: not ray.get(a.has_garbage.remote()), |
288 | | - timeout=RAY_GC_MIN_COLLECT_INTERVAL * 2, |
289 | | - ) |
| 273 | + # 2b) Check that GC is called. |
| 274 | + wait_for_condition( |
| 275 | + lambda: not ray.get(a.has_garbage.remote()), |
| 276 | + timeout=5, |
| 277 | + ) |
290 | 278 |
|
291 | | - finally: |
292 | | - gc.enable() |
| 279 | + gc.enable() |
293 | 280 |
|
294 | 281 |
|
295 | 282 | def test_gc_manager_thread_basic_functionality(): |
296 | 283 | mock_gc_collect = Mock(return_value=10) |
297 | 284 |
|
298 | | - gc_thread = PythonGCThread(min_interval_s=1, gc_collect_func=mock_gc_collect) |
| 285 | + gc_thread = PythonGCThread(gc_collect_func=mock_gc_collect) |
| 286 | + gc_thread.start() |
| 287 | + assert gc_thread.is_alive() |
299 | 288 |
|
300 | | - try: |
301 | | - gc_thread.start() |
302 | | - assert gc_thread.is_alive() |
303 | | - |
304 | | - gc_thread.trigger_gc() |
| 289 | + gc_thread.trigger_gc() |
| 290 | + wait_for_condition(lambda: mock_gc_collect.call_count == 1, timeout=2) |
305 | 291 |
|
306 | | - wait_for_condition(lambda: mock_gc_collect.call_count == 1, timeout=2) |
| 292 | + gc_thread.trigger_gc() |
| 293 | + wait_for_condition(lambda: mock_gc_collect.call_count == 2, timeout=2) |
307 | 294 |
|
308 | | - mock_gc_collect.assert_called_once() |
309 | | - |
310 | | - finally: |
311 | | - gc_thread.stop() |
312 | | - assert not gc_thread.is_alive() |
313 | | - |
314 | | - |
315 | | -def test_gc_manager_thread_min_interval_throttling(): |
316 | | - mock_gc_collect = Mock(return_value=5) |
317 | | - |
318 | | - gc_thread = PythonGCThread(min_interval_s=2, gc_collect_func=mock_gc_collect) |
319 | | - |
320 | | - try: |
321 | | - gc_thread.start() |
322 | | - |
323 | | - for _ in range(3): |
324 | | - gc_thread.trigger_gc() |
325 | | - time.sleep(1) |
326 | | - |
327 | | - wait_for_condition(lambda: mock_gc_collect.call_count == 2, timeout=2) |
328 | | - |
329 | | - assert mock_gc_collect.call_count == 2 |
330 | | - |
331 | | - finally: |
332 | | - gc_thread.stop() |
| 295 | + gc_thread.stop() |
| 296 | + assert not gc_thread.is_alive() |
333 | 297 |
|
334 | 298 |
|
335 | 299 | def test_gc_manager_thread_exception_handling(): |
336 | 300 | mock_gc_collect = Mock(side_effect=RuntimeError("GC failed")) |
337 | 301 |
|
338 | | - gc_thread = PythonGCThread(min_interval_s=5, gc_collect_func=mock_gc_collect) |
| 302 | + gc_thread = PythonGCThread(gc_collect_func=mock_gc_collect) |
| 303 | + gc_thread.start() |
339 | 304 |
|
340 | | - try: |
341 | | - gc_thread.start() |
342 | | - |
343 | | - for _ in range(3): |
344 | | - gc_thread.trigger_gc() |
345 | | - time.sleep(0.1) |
| 305 | + for _ in range(3): |
| 306 | + gc_thread.trigger_gc() |
| 307 | + time.sleep(0.1) |
346 | 308 |
|
347 | | - assert gc_thread.is_alive() |
348 | | - mock_gc_collect.assert_called_once() |
| 309 | + assert gc_thread.is_alive() |
| 310 | + assert mock_gc_collect.call_count == 3 |
349 | 311 |
|
350 | | - finally: |
351 | | - gc_thread.stop() |
| 312 | + gc_thread.stop() |
352 | 313 |
|
353 | 314 |
|
354 | 315 | if __name__ == "__main__": |
|
0 commit comments