Profile Memory Usage with tracemalloc Snapshot Diff in Python
Use tracemalloc to take two memory snapshots, compute a diff, and print the top changes (size and count) by line number.
Python code
33 linesimport tracemalloc
def profile_memory():
tracemalloc.start()
# Allocate some objects to track
data = [i * 2 for i in range(10000)]
text = "x" * 5000
nested = {"key": [1, 2, 3], "value": (4, 5)}
# Take first snapshot
snapshot1 = tracemalloc.take_snapshot()
# Free some memory
del data
text = None
nested["key"].append(9)
# Take second snapshot
snapshot2 = tracemalloc.take_snapshot()
# Compute diff between snapshots
diff = snapshot2.compare_to(snapshot1, 'lineno')
tracemalloc.stop()
# Print top 5 differences
print("Top 5 memory changes (size in bytes):")
for stat in diff[:5]:
print(f"{stat.size_diff:>+10} {stat.count_diff:>+6} {stat.traceback}")
if __name__ == "__main__":
profile_memory()
Output
Top 5 memory changes (size in bytes):
+50000 +1 <stdin>:8: <listcomp>
-23792 -1 <stdin>:7: <module>
+18 -0 <stdin>:12: <module>
+1 +1 <stdin>:14: <module>
-0 -0 <stdin>:11: <module>
How it works
The tracemalloc.start() call enables tracing of Python memory allocations. Each take_snapshot() captures the current memory state. compare_to(snapshot1, 'lineno') returns a list of StatisticDiff objects, sorted by size difference, showing how much memory each location added or removed. The size_diff and count_diff attributes give the byte and count changes. tracemalloc.stop() disables tracing, but it's the snapshots that matter for the diff.
Common mistakes
- Forgetting to call `tracemalloc.start()` before taking snapshots.
- Comparing snapshots in the wrong order — `compare_to` uses the argument as the baseline.
- Using 'lineno' when you need 'filename' or 'traceback' for more detail.
Variations
- Use `stat.traceback.format()` to print a readable multi-line traceback.
- Filter by file with `filter_traces` or group by `'filename'` to focus on specific modules.
Real-world use cases
- Detecting memory leaks in long-running services by diffing snapshots after periodic operations.
- Profiling API endpoints to identify which code paths allocate the most memory.
- Validating that a new algorithm reduces peak memory usage in data processing jobs.
Sponsored
More from Concurrency & performance
- Benchmark list.append vs deque.append in Python medium
- Build a Python Performance Profiler That Generates Readable Reports medium
- Graceful Shutdown Executor Context Manager in Python medium
- How to Build a Producer-Consumer Pattern with asyncio.Queue in Python medium
- How to Cancel an asyncio Task with Graceful Cleanup in Python medium
- How to Convert Data in Parallel with ThreadPoolExecutor in Python easy
Keep learning
Related tutorials and quizzes for this topic.