The problem
You need to profile function performance for optimization.
The solution
import functools
import time
import tracemalloc
from typing import Callable
def profile(print_stats: bool = True) -> Callable:
"""Decorator to profile function execution time and memory usage."""
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Start memory tracking
tracemalloc.start()
# Time execution
start_time = time.perf_counter()
try:
result = func(*args, **kwargs)
finally:
# Calculate execution time
end_time = time.perf_counter()
execution_time = end_time - start_time
# Get memory statistics
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
if print_stats:
print(f"Function: {func.__name__}")
print(f"Execution time: {execution_time:.6f} seconds")
print(f"Current memory usage: {current / 1024:.2f} KB")
print(f"Peak memory usage: {peak / 1024:.2f} KB")
print(f"Memory delta: {(peak - current) / 1024:.2f} KB")
return result
return wrapper
return decoratorParameters
print_statsboolWhether to print profiling statistics
Put it to work
@profile(print_stats=True)
def process_large_data(size: int):
"""Process a large dataset."""
data = [i ** 2 for i in range(size)]
return sum(data) / len(data) if data else 0
# Will print performance statistics
result = process_large_data(100000)