From baf20119687b161cef066b9c66e988fa931be3b6 Mon Sep 17 00:00:00 2001 From: Matthew Neeley Date: Thu, 23 Mar 2023 13:40:36 -0700 Subject: [PATCH 1/2] Compute block_counts iteratively with explicit stack This avoids RecursionError when processing some profiles. Could get a similar effect using `sys.setrecursionlimit` with the existing recursive implementation, but there's no way to choose a sufficiently large limit, so a non-recursive implementation seems safer. --- flameprof.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/flameprof.py b/flameprof.py index ba9c3a8..20fde3f 100644 --- a/flameprof.py +++ b/flameprof.py @@ -141,13 +141,16 @@ def prepare(funcs, calls, threshold=0.0001): bblocks = [] block_counts = Counter() - def _counts(parent, visited, level=0): + visited = set() + todo = [('root', set(), 0)] + while todo: + parent, visited, level = todo.pop(-1) for child in funcs[parent]['calls']: k = parent, child block_counts[k] += 1 if block_counts[k] < 2: if k not in visited: - _counts(child, visited | {k}, level+1) + todo.append((child, visited | {k}, level+1)) def _calc(parent, timings, level, origin, visited, trace=(), pccnt=1, pblock=None): childs = funcs[parent]['calls'] @@ -227,7 +230,6 @@ def _calc_back(names, level, to, origin, visited, pw): origin += ttt maxw = funcs['root']['stat'][3] * 1.0 - _counts('root', set()) _calc('root', (1, 1, maxw, maxw), 0, 0, set()) _calc_back((f for f in funcs if f != 'root'), 0, None, 0, set(), 0) From 3dfa9aa6e2aa461e129dbab7b766560fce941578 Mon Sep 17 00:00:00 2001 From: Matthew Neeley Date: Mon, 23 Sep 2024 15:44:25 -0700 Subject: [PATCH 2/2] Remove extra `visited` set --- flameprof.py | 1 - 1 file changed, 1 deletion(-) diff --git a/flameprof.py b/flameprof.py index 20fde3f..4191a2b 100644 --- a/flameprof.py +++ b/flameprof.py @@ -141,7 +141,6 @@ def prepare(funcs, calls, threshold=0.0001): bblocks = [] block_counts = Counter() - visited = set() todo = [('root', set(), 0)] while todo: parent, visited, level = todo.pop(-1)