changeset 45797:5b6c0af021da

utils: helper function to print top memory allocation site The memorytop function uses Python's tracemalloc module to show the source lines / backtraces with the largest remaining allocations. This allows identifying the origins of active memory by placing calls in strategic locations. Allocations from C extensions will show up as long as they are using the Python allocators. Differential Revision: https://phab.mercurial-scm.org/D9236
author Joerg Sonnenberger <joerg@bec.de>
date Wed, 21 Oct 2020 22:30:42 +0200
parents e9555305c5c6
children ff7e0ca666e8
files mercurial/utils/memorytop.py
diffstat 1 files changed, 44 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/utils/memorytop.py	Wed Oct 21 22:30:42 2020 +0200
@@ -0,0 +1,44 @@
+# memorytop requires Python 3.4
+#
+# Usage: set PYTHONTRACEMALLOC=n in the environment of the hg invocation,
+# where n>= is the number of frames to show in the backtrace. Put calls to
+# memorytop in strategic places to show the current memory use by allocation
+# site.
+
+import gc
+import tracemalloc
+
+
+def memorytop(limit=10):
+    gc.collect()
+    snapshot = tracemalloc.take_snapshot()
+
+    snapshot = snapshot.filter_traces(
+        (
+            tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
+            tracemalloc.Filter(False, "<frozen importlib._bootstrap_external>"),
+            tracemalloc.Filter(False, "<unknown>"),
+        )
+    )
+    stats = snapshot.statistics('traceback')
+
+    total = sum(stat.size for stat in stats)
+    print("\nTotal allocated size: %.1f KiB\n" % (total / 1024))
+    print("Lines with the biggest net allocations")
+    for index, stat in enumerate(stats[:limit], 1):
+        print(
+            "#%d: %d objects using %.1f KiB"
+            % (index, stat.count, stat.size / 1024)
+        )
+        for line in stat.traceback.format(most_recent_first=True):
+            print('    ', line)
+
+    other = stats[limit:]
+    if other:
+        size = sum(stat.size for stat in other)
+        count = sum(stat.count for stat in other)
+        print(
+            "%s other: %d objects using %.1f KiB"
+            % (len(other), count, size / 1024)
+        )
+    print()