| """Scripts and classifiers for external inspection validation. |
| |
| Classifiers detect only recognized impossible patterns. They do not validate |
| entire stacks. False does not imply that the stack as a whole is valid. |
| """ |
| import os |
| |
| |
| def _get_lineno(frame, default=None): |
| if frame is None: |
| return default |
| loc = getattr(frame, "location", None) |
| return getattr(loc, "lineno", default) if loc is not None else default |
| |
| |
| CODE = '''\ |
| import time |
| import os |
| import sys |
| import math |
| |
| def slow_fibonacci(n): |
| """Intentionally slow recursive fibonacci - should show up prominently in profiler""" |
| if n <= 1: |
| return n |
| return slow_fibonacci(n-1) + slow_fibonacci(n-2) |
| |
| def medium_computation(): |
| """Medium complexity function""" |
| result = 0 |
| for i in range(1000): |
| result += math.sqrt(i) * math.sin(i) |
| return result |
| |
| def fast_loop(): |
| """Fast simple loop""" |
| total = 0 |
| for i in range(100): |
| total += i |
| return total |
| |
| def string_operations(): |
| """String manipulation that should be visible in profiler""" |
| text = "hello world " * 100 |
| words = text.split() |
| return " ".join(reversed(words)) |
| |
| def nested_calls(): |
| """Nested function calls to test call stack depth""" |
| def level1(): |
| def level2(): |
| def level3(): |
| return medium_computation() |
| return level3() |
| return level2() |
| return level1() |
| |
| def main_loop(): |
| """Main computation loop with different execution paths""" |
| iteration = 0 |
| |
| while True: |
| iteration += 1 |
| |
| # Different execution paths with different frequencies |
| if iteration % 50 == 0: |
| # Expensive operation - should show high per-call time |
| result = slow_fibonacci(20) |
| |
| elif iteration % 10 == 0: |
| # Medium operation |
| result = nested_calls() |
| |
| elif iteration % 5 == 0: |
| # String operations |
| result = string_operations() |
| |
| else: |
| # Fast operation - most common |
| result = fast_loop() |
| |
| # Small delay to make sampling more interesting |
| time.sleep(0.001) |
| |
| if __name__ == "__main__": |
| main_loop() |
| ''' |
| |
| DEEP_STATIC_CODE = """\ |
| import time |
| def factorial(n): |
| if n <= 1: |
| time.sleep(10000) |
| return 1 |
| return n * factorial(n-1) |
| |
| factorial(900) |
| """ |
| |
| CODE_WITH_TONS_OF_THREADS = '''\ |
| import time |
| import threading |
| import random |
| import math |
| |
| def cpu_intensive_work(): |
| """Do some CPU intensive calculations""" |
| result = 0 |
| for _ in range(10000): |
| result += math.sin(random.random()) * math.cos(random.random()) |
| return result |
| |
| def io_intensive_work(): |
| """Simulate IO intensive work with sleeps""" |
| time.sleep(0.1) |
| |
| def mixed_workload(): |
| """Mix of CPU and IO work""" |
| while True: |
| if random.random() < 0.3: |
| cpu_intensive_work() |
| else: |
| io_intensive_work() |
| |
| def create_threads(n): |
| """Create n threads doing mixed workloads""" |
| threads = [] |
| for _ in range(n): |
| t = threading.Thread(target=mixed_workload, daemon=True) |
| t.start() |
| threads.append(t) |
| return threads |
| |
| # Start with 5 threads |
| active_threads = create_threads(5) |
| |
| # Main thread manages threads and does work |
| while True: |
| # Randomly add threads up to the limit |
| if random.random() < 0.1: # 10% chance each iteration |
| if random.random() < 0.5 and len(active_threads) < 100: |
| new_count = min( |
| random.randint(1, 5), |
| 100 - len(active_threads), |
| ) |
| new_threads = create_threads(new_count) |
| active_threads.extend(new_threads) |
| |
| cpu_intensive_work() |
| time.sleep(0.05) |
| ''' |
| |
| ASYNC_CODE = '''\ |
| import asyncio |
| import contextlib |
| import math |
| |
| def compute_slice(seed): |
| result = 0.0 |
| for i in range(2000): |
| result += math.sin(seed + i) * math.sqrt(i + 1) |
| return result |
| |
| async def leaf_task(seed): |
| total = 0.0 |
| while True: |
| total += compute_slice(seed) |
| await asyncio.sleep(0) |
| |
| async def parent_task(seed): |
| child = asyncio.create_task(leaf_task(seed + 1000), name=f"leaf-{seed}") |
| try: |
| while True: |
| compute_slice(seed) |
| await asyncio.sleep(0.001) |
| finally: |
| child.cancel() |
| with contextlib.suppress(asyncio.CancelledError): |
| await child |
| |
| async def main(): |
| tasks = [ |
| asyncio.create_task(parent_task(i), name=f"parent-{i}") |
| for i in range(8) |
| ] |
| await asyncio.gather(*tasks) |
| |
| if __name__ == "__main__": |
| asyncio.run(main()) |
| ''' |
| |
| |
| FLAT_ALTERNATING_CODE = """\ |
| def leaf_a(): return sum(range(50)) |
| def leaf_b(): return sum(range(50)) |
| def hot_a(): return leaf_a() |
| def hot_b(): return leaf_b() |
| while True: |
| hot_a(); hot_b() |
| """ |
| |
| |
| def _expected_lines(code): |
| expected = {} |
| for number, line in enumerate(code.splitlines(), 1): |
| stripped = line.strip() |
| if stripped.startswith("def "): |
| expected[stripped[4:].split("(")[0].strip()] = number |
| return expected |
| |
| |
| FLAT_ALTERNATING_LINES = _expected_lines(FLAT_ALTERNATING_CODE) |
| |
| |
| def classify_flat(frames): |
| present = {} |
| for frame in frames: |
| if frame.funcname in FLAT_ALTERNATING_LINES: |
| present[frame.funcname] = _get_lineno(frame, -1) |
| if not present: |
| return False |
| for name, lineno in present.items(): |
| if lineno != FLAT_ALTERNATING_LINES[name]: |
| return True |
| hot_a, hot_b = "hot_a" in present, "hot_b" in present |
| leaf_a, leaf_b = "leaf_a" in present, "leaf_b" in present |
| any_a = leaf_a or hot_a |
| any_b = leaf_b or hot_b |
| return (any_a and any_b) or (leaf_a and not hot_a) or (leaf_b and not hot_b) |
| |
| |
| NESTED_ALTERNATING_CODE = """\ |
| def burn_a(): |
| total = 0 |
| for i in range(20000): |
| total += i |
| return total |
| |
| def burn_b(): |
| total = 0 |
| for i in range(20000): |
| total += i |
| return total |
| |
| def a_leaf(): |
| return burn_a() |
| |
| def b_leaf(): |
| return burn_b() |
| |
| def a_parent(): |
| return a_leaf() |
| |
| def b_parent(): |
| return b_leaf() |
| |
| while True: |
| a_parent() |
| b_parent() |
| """ |
| |
| |
| NESTED_ALTERNATING_BRANCHES = { |
| "a": ["a_parent", "a_leaf", "burn_a"], |
| "b": ["b_parent", "b_leaf", "burn_b"], |
| } |
| |
| |
| def classify_nested(frames): |
| frame_names = [frame.funcname for frame in frames] |
| names = set(frame_names) |
| present = [ |
| family |
| for family, chain in NESTED_ALTERNATING_BRANCHES.items() |
| if names.intersection(chain) |
| ] |
| if len(present) > 1: |
| return True |
| if not present: |
| return False |
| chain = NESTED_ALTERNATING_BRANCHES[present[0]] |
| active = [name for name in chain if name in names] |
| depth = chain.index(active[-1]) |
| if len(active) != depth + 1: |
| return True |
| indices = [frame_names.index(name) for name in reversed(active)] |
| return indices != sorted(indices) |
| |
| |
| SHARED_LEAF_CODE = """\ |
| def shared_leaf(long_run): |
| total = 0 |
| if long_run: |
| for i in range(50000): |
| total += i |
| else: |
| for i in range(200): |
| total += i |
| return total |
| |
| def a_wrapper(): |
| return shared_leaf(False) |
| |
| def b_wrapper(): |
| return shared_leaf(True) |
| |
| while True: |
| a_wrapper() |
| b_wrapper() |
| """ |
| |
| |
| def _branch_lines(code, marker): |
| for number, line in enumerate(code.splitlines(), 1): |
| if marker in line: |
| return {number, number + 1} |
| return set() |
| |
| |
| SHARED_LEAF_LONG_LINES = _branch_lines(SHARED_LEAF_CODE, "range(50000)") |
| SHARED_LEAF_SHORT_LINES = _branch_lines(SHARED_LEAF_CODE, "range(200)") |
| |
| |
| def classify_shared(frames): |
| frame_names = [frame.funcname for frame in frames] |
| names = set(frame_names) |
| if "a_wrapper" in names and "b_wrapper" in names: |
| return True |
| if "shared_leaf" not in names: |
| return False |
| index = frame_names.index("shared_leaf") |
| parent = frame_names[index + 1] if index + 1 < len(frame_names) else None |
| if parent not in ("a_wrapper", "b_wrapper"): |
| return True |
| lineno = _get_lineno(frames[index], -1) |
| if lineno in SHARED_LEAF_LONG_LINES: |
| return parent != "b_wrapper" |
| if lineno in SHARED_LEAF_SHORT_LINES: |
| return parent != "a_wrapper" |
| return False |
| |
| |
| GEN_ALTERNATING_CODE = """\ |
| def agen(n): |
| total = 0 |
| for i in range(n): |
| total += i |
| yield i |
| |
| def bgen(n): |
| total = 0 |
| for i in range(n): |
| total += i |
| yield i |
| |
| def drv_a(): |
| for _ in agen(60): |
| pass |
| |
| def drv_b(): |
| for _ in bgen(60): |
| pass |
| |
| while True: |
| drv_a() |
| drv_b() |
| """ |
| |
| |
| def classify_gen(frames): |
| names = {frame.funcname for frame in frames} |
| return ("agen" in names and "drv_b" in names) or ( |
| "bgen" in names and "drv_a" in names |
| ) |
| |
| |
| DEEP_RECURSION_CODE = """\ |
| def leaf(): |
| total = 0 |
| for i in range(40): |
| total += i |
| |
| def a(n): |
| return a(n - 1) if n else leaf() |
| |
| def b(n): |
| return b(n - 1) if n else leaf() |
| |
| while True: |
| a(300) |
| b(300) |
| """ |
| |
| |
| def classify_recursion(frames): |
| names = {frame.funcname for frame in frames} |
| return "a" in names and "b" in names |
| |
| |
| ASYNC_RUNNING_TASK_CODE = """\ |
| import asyncio |
| |
| |
| def leaf_hot(n): |
| return sum(range(n)) |
| |
| |
| def leaf_rare(n): |
| return sum(range(n)) |
| |
| |
| async def run_hot(): |
| while True: |
| leaf_hot(50000) |
| await asyncio.sleep(0) |
| |
| |
| async def run_rare(k): |
| while True: |
| leaf_rare(500) |
| await asyncio.sleep(0) |
| |
| |
| async def main(): |
| tasks = [asyncio.create_task(run_hot(), name="hot")] |
| for k in range(8): |
| tasks.append(asyncio.create_task(run_rare(k), name=f"rare{k}")) |
| await asyncio.gather(*tasks) |
| |
| |
| asyncio.run(main()) |
| """ |
| |
| |
| def _name_tag(label): |
| label = (label or "").lower() |
| return "hot" if "hot" in label else "rare" if "rare" in label else None |
| |
| |
| def _frame_tag(frames): |
| fns = {frame.funcname for frame in frames} |
| hot = bool(fns & {"run_hot", "leaf_hot"}) |
| rare = bool(fns & {"run_rare", "leaf_rare"}) |
| return ( |
| "mixed" |
| if (hot and rare) |
| else "hot" |
| if hot |
| else "rare" |
| if rare |
| else None |
| ) |
| |
| |
| def classify_async_running_task(unit): |
| name = _name_tag(unit[1]) |
| frame = _frame_tag(unit[3]) |
| return name is not None and frame is not None and frame != name |
| |
| |
| CODE_OBJECT_REUSE_CODE = """\ |
| SRC_A = "def func_a(n):\\n total=0\\n for i in range(n): total+=i*i\\n return total\\n" |
| SRC_B = "def func_b(n):\\n total=0\\n for i in range(n): total+=i*i\\n return total\\n" |
| WORK = 60000 |
| |
| |
| def build_a(): |
| ns = {} |
| code = compile(SRC_A, "A_file.py", "exec") |
| exec(code, ns) |
| return ns["func_a"], code |
| |
| |
| def build_b(): |
| ns = {} |
| code = compile(SRC_B, "B_file.py", "exec") |
| exec(code, ns) |
| return ns["func_b"], code |
| |
| |
| while True: |
| fa, ca = build_a() |
| fa(WORK) # call_a |
| del fa, ca |
| fb, cb = build_b() |
| fb(WORK) # call_b |
| del fb, cb |
| """ |
| |
| |
| def _marker_line(code, marker): |
| for number, line in enumerate(code.splitlines(), 1): |
| if marker in line: |
| return number |
| return None |
| |
| |
| CALL_A_LINE = _marker_line(CODE_OBJECT_REUSE_CODE, "# call_a") |
| CALL_B_LINE = _marker_line(CODE_OBJECT_REUSE_CODE, "# call_b") |
| |
| |
| def classify_code_object_reuse(frames): |
| real = [f for f in frames if f.funcname != "<GC>"] |
| leaf = next((f for f in real if f.funcname in ("func_a", "func_b")), None) |
| if leaf is None: |
| return False |
| base = os.path.basename(leaf.filename) |
| fn = leaf.funcname |
| if (fn == "func_a" and base == "B_file.py") or ( |
| fn == "func_b" and base == "A_file.py" |
| ): |
| return True |
| index = real.index(leaf) |
| caller = real[index + 1] if index + 1 < len(real) else None |
| line = _get_lineno(caller) |
| if line == CALL_A_LINE and fn == "func_b": |
| return True |
| if line == CALL_B_LINE and fn == "func_a": |
| return True |
| return False |
| |
| |
| OVERSIZED_CHUNK_CODE = """\ |
| NLOCALS = 1800 |
| |
| def make(name, tag, hotbody): |
| params = ", ".join(f"x{i}=0" for i in range(NLOCALS)) |
| src = ( |
| f"def hot_{tag}():\\n{hotbody}\\n" |
| f"def {name}({params}):\\n return hot_{tag}()\\n" |
| ) |
| exec(compile(src, f"{tag}.py", "exec"), globals()) |
| |
| make("big_a", "a", " s=0\\n for i in range(2000):\\n s+=i*3\\n return s") |
| make("big_b", "b", " s=1\\n for i in range(2000):\\n s^=(i<<1)\\n return s") |
| |
| while True: |
| big_a() |
| big_b() |
| """ |
| |
| |
| OVERSIZED_A_FUNCS = {"big_a", "hot_a"} |
| OVERSIZED_B_FUNCS = {"big_b", "hot_b"} |
| |
| |
| def classify_oversized_chunk(frames): |
| saw_a = saw_b = False |
| for frame in frames: |
| base = os.path.basename(frame.filename) |
| fn = frame.funcname |
| if base == "a.py": |
| if fn in OVERSIZED_A_FUNCS: |
| saw_a = True |
| elif fn in OVERSIZED_B_FUNCS: |
| return True |
| elif base == "b.py": |
| if fn in OVERSIZED_B_FUNCS: |
| saw_b = True |
| elif fn in OVERSIZED_A_FUNCS: |
| return True |
| return saw_a and saw_b |
| |
| |
| CODE_EXAMPLES = { |
| "basic": { |
| "code": CODE, |
| "description": "Mixed workload with fibonacci, computations, and string operations", |
| }, |
| "deep_static": { |
| "code": DEEP_STATIC_CODE, |
| "description": "Deep recursive call stack with 900+ frames (factorial)", |
| }, |
| "threads": { |
| "code": CODE_WITH_TONS_OF_THREADS, |
| "description": "Tons of threads doing mixed CPU/IO work", |
| }, |
| "asyncio": { |
| "code": ASYNC_CODE, |
| "description": "Asyncio tasks with active and awaited coroutine chains", |
| }, |
| } |
| |
| CASES = { |
| "basic": (CODE, None), |
| "deep_static": (DEEP_STATIC_CODE, None), |
| "threads": (CODE_WITH_TONS_OF_THREADS, None), |
| "asyncio": (ASYNC_CODE, None, "get_async_stack_trace"), |
| "flat_alternating": (FLAT_ALTERNATING_CODE, classify_flat), |
| "nested_alternating": (NESTED_ALTERNATING_CODE, classify_nested), |
| "shared_leaf": (SHARED_LEAF_CODE, classify_shared), |
| "gen_alternating": (GEN_ALTERNATING_CODE, classify_gen), |
| "deep_recursion": (DEEP_RECURSION_CODE, classify_recursion), |
| "async_running_task": ( |
| ASYNC_RUNNING_TASK_CODE, |
| classify_async_running_task, |
| "get_async_stack_trace", |
| ), |
| "code_object_reuse": (CODE_OBJECT_REUSE_CODE, classify_code_object_reuse), |
| "oversized_chunk": (OVERSIZED_CHUNK_CODE, classify_oversized_chunk), |
| } |