|
2 | 2 |
|
3 | 3 | # pyre-strict |
4 | 4 |
|
5 | | -import gc |
6 | | -import multiprocessing |
7 | | -import os |
8 | 5 | import subprocess |
9 | 6 | import sys |
10 | 7 | import tempfile |
11 | 8 | import textwrap |
12 | 9 | import unittest |
13 | 10 | from pathlib import Path |
14 | | -from typing import Any |
15 | 11 |
|
16 | 12 | import cinderx |
17 | 13 | from cinderx.test_support import ENCODING, passUnless, subprocess_env |
18 | 14 |
|
19 | 15 |
|
20 | | -def _run_gc_settings(result_queue: "multiprocessing.Queue[tuple[int, Any]]") -> None: |
21 | | - """Child process function to test gc.get_threshold().""" |
22 | | - try: |
23 | | - result = gc.get_threshold() |
24 | | - result_queue.put((0, result)) |
25 | | - except Exception as e: |
26 | | - result_queue.put((1, str(e))) |
27 | | - |
28 | | - |
29 | | -def _run_parallel_gc_settings( |
30 | | - result_queue: "multiprocessing.Queue[tuple[int, Any]]", |
31 | | -) -> None: |
32 | | - """Child process function to test cinderx.get_parallel_gc_settings().""" |
33 | | - try: |
34 | | - result = cinderx.get_parallel_gc_settings() |
35 | | - result_queue.put((0, result)) |
36 | | - except Exception as e: |
37 | | - result_queue.put((1, str(e))) |
38 | | - |
39 | | - |
40 | 16 | @passUnless(cinderx.has_parallel_gc(), "Testing Parallel GC Enablement") |
41 | 17 | class TestEnablingParallelGc(unittest.TestCase): |
42 | 18 | def test_gc_settings(self) -> None: |
43 | | - # Set environment variables for the child process |
44 | | - os.environ["PARALLEL_GC_ENABLED"] = "1" |
45 | | - os.environ["PARALLEL_GC_THRESHOLD_GEN0"] = "1000" |
46 | | - os.environ["PARALLEL_GC_THRESHOLD_GEN1"] = "5" |
47 | | - os.environ["PARALLEL_GC_THRESHOLD_GEN2"] = "5" |
48 | | - |
49 | | - try: |
50 | | - ctx = multiprocessing.get_context("spawn") |
51 | | - result_queue: multiprocessing.Queue[tuple[int, Any]] = ctx.Queue() |
52 | | - proc = ctx.Process(target=_run_gc_settings, args=(result_queue,)) |
53 | | - proc.start() |
54 | | - proc.join(timeout=30) |
| 19 | + codestr = textwrap.dedent(""" |
| 20 | + import cinderx |
55 | 21 |
|
56 | | - self.assertEqual(proc.exitcode, 0) |
57 | | - returncode, result = result_queue.get(timeout=5) |
58 | | - self.assertEqual(returncode, 0) |
59 | | - self.assertEqual(result, (1000, 5, 5)) |
60 | | - finally: |
61 | | - proc.terminate() |
62 | | - del os.environ["PARALLEL_GC_ENABLED"] |
63 | | - del os.environ["PARALLEL_GC_THRESHOLD_GEN0"] |
64 | | - del os.environ["PARALLEL_GC_THRESHOLD_GEN1"] |
65 | | - del os.environ["PARALLEL_GC_THRESHOLD_GEN2"] |
| 22 | + import gc |
| 23 | + def g(): |
| 24 | + return gc.get_threshold() |
| 25 | + print(g()) |
| 26 | + """) |
| 27 | + with tempfile.TemporaryDirectory() as tmp: |
| 28 | + dirpath = Path(tmp) |
| 29 | + codepath = dirpath / "mod.py" |
| 30 | + codepath.write_text(codestr) |
| 31 | + args = [sys.executable] |
| 32 | + args.append("mod.py") |
| 33 | + proc = subprocess.run( |
| 34 | + args, |
| 35 | + cwd=tmp, |
| 36 | + stdout=subprocess.PIPE, |
| 37 | + encoding=ENCODING, |
| 38 | + env={ |
| 39 | + **subprocess_env(), |
| 40 | + "PARALLEL_GC_ENABLED": "1", |
| 41 | + "PARALLEL_GC_THRESHOLD_GEN0": "1000", |
| 42 | + "PARALLEL_GC_THRESHOLD_GEN1": "5", |
| 43 | + "PARALLEL_GC_THRESHOLD_GEN2": "5", |
| 44 | + }, |
| 45 | + ) |
| 46 | + self.assertEqual(proc.returncode, 0, proc) |
| 47 | + actual_stdout = list(proc.stdout.strip().split("\n")) |
| 48 | + self.assertEqual(actual_stdout, ["(1000, 5, 5)"]) |
66 | 49 |
|
67 | 50 | def test_parallel_gc_settings(self) -> None: |
68 | | - # Set environment variables for the child process |
69 | | - os.environ["PARALLEL_GC_ENABLED"] = "1" |
70 | | - os.environ["PARALLEL_GC_NUM_THREADS"] = "4" |
71 | | - os.environ["PARALLEL_GC_MIN_GENERATION"] = "2" |
72 | | - |
73 | | - try: |
74 | | - ctx = multiprocessing.get_context("spawn") |
75 | | - result_queue: multiprocessing.Queue[tuple[int, Any]] = ctx.Queue() |
76 | | - proc = ctx.Process(target=_run_parallel_gc_settings, args=(result_queue,)) |
77 | | - proc.start() |
78 | | - proc.join(timeout=30) |
79 | | - |
80 | | - self.assertEqual(proc.exitcode, 0) |
81 | | - returncode, result = result_queue.get(timeout=5) |
82 | | - self.assertEqual(returncode, 0) |
83 | | - self.assertEqual(result, {"num_threads": 4, "min_generation": 2}) |
84 | | - finally: |
85 | | - proc.terminate() |
86 | | - del os.environ["PARALLEL_GC_ENABLED"] |
87 | | - del os.environ["PARALLEL_GC_NUM_THREADS"] |
88 | | - del os.environ["PARALLEL_GC_MIN_GENERATION"] |
| 51 | + codestr = textwrap.dedent(""" |
| 52 | + import cinderx |
| 53 | + def g(): |
| 54 | + return cinderx.get_parallel_gc_settings() |
| 55 | + print(g()) |
| 56 | + """) |
| 57 | + with tempfile.TemporaryDirectory() as tmp: |
| 58 | + dirpath = Path(tmp) |
| 59 | + codepath = dirpath / "mod.py" |
| 60 | + codepath.write_text(codestr) |
| 61 | + args = [sys.executable] |
| 62 | + args.append("mod.py") |
| 63 | + proc = subprocess.run( |
| 64 | + args, |
| 65 | + cwd=tmp, |
| 66 | + stdout=subprocess.PIPE, |
| 67 | + encoding=ENCODING, |
| 68 | + env={ |
| 69 | + **subprocess_env(), |
| 70 | + "PARALLEL_GC_ENABLED": "1", |
| 71 | + "PARALLEL_GC_NUM_THREADS": "4", |
| 72 | + "PARALLEL_GC_MIN_GENERATION": "2", |
| 73 | + }, |
| 74 | + ) |
| 75 | + self.assertEqual(proc.returncode, 0, proc) |
| 76 | + actual_stdout = list(proc.stdout.strip().split("\n")) |
| 77 | + self.assertEqual(actual_stdout, ["{'num_threads': 4, 'min_generation': 2}"]) |
89 | 78 |
|
90 | 79 | def test_parallel_gc_failure_high_min_gen_number(self) -> None: |
91 | 80 | codestr = textwrap.dedent(""" |
|
0 commit comments