|
1 | 1 | import time
|
2 | 2 | import tracemalloc
|
3 | 3 |
|
| 4 | + |
4 | 5 | def performance(func):
|
5 |
| - setattr(performance, '_count', 0) |
6 |
| - setattr(performance, '_time', 0.0) |
7 |
| - setattr(performance, '_memory', 0.0) |
| 6 | + """ |
| 7 | + A decorator to measure the performance of a function. |
| 8 | + Attributes: |
| 9 | + counter: The number of times the function has been called. |
| 10 | + total_time: The total time the function has taken to run. |
| 11 | + total_mem: The total peak memory used by the function in bytes. |
| 12 | + """ |
| 13 | + |
| 14 | + # Initialize attributes if they don't already exist |
| 15 | + if not hasattr(performance, 'counter'): |
| 16 | + performance.counter = 0 |
| 17 | + if not hasattr(performance, 'total_time'): |
| 18 | + performance.total_time = 0.0 |
| 19 | + if not hasattr(performance, 'total_mem'): |
| 20 | + performance.total_mem = 0 |
8 | 21 |
|
9 | 22 | def wrapper(*args, **kwargs):
|
10 |
| - count = getattr(performance, '_count') + 1 |
11 |
| - setattr(performance, '_count', count) |
| 23 | + # Increment call counter |
| 24 | + performance.counter += 1 |
12 | 25 |
|
13 |
| - start = time.time() |
| 26 | + # Measure execution time and memory usage |
| 27 | + start_time = time.time() |
14 | 28 | tracemalloc.start()
|
15 | 29 |
|
16 | 30 | try:
|
17 |
| - func(*args, **kwargs) |
| 31 | + result = func(*args, **kwargs) |
18 | 32 | except Exception as exc:
|
19 | 33 | print(f"Error: {exc}")
|
| 34 | + result = None |
20 | 35 | finally:
|
21 |
| - end = time.time() |
22 |
| - curr, peak = tracemalloc.get_traced_memory() |
| 36 | + end_time = time.time() |
| 37 | + current, peak = tracemalloc.get_traced_memory() |
23 | 38 | tracemalloc.stop()
|
24 | 39 |
|
25 |
| - elapsed = end - start |
26 |
| - total_time = getattr(performance, '_time') + elapsed |
27 |
| - total_mem = getattr(performance, '_memory') + peak |
| 40 | + # Update performance metrics |
| 41 | + time_taken = end_time - start_time |
| 42 | + performance.total_time += time_taken |
| 43 | + performance.total_mem += peak |
28 | 44 |
|
29 |
| - setattr(performance, '_time', total_time) |
30 |
| - setattr(performance, '_memory', total_mem) |
| 45 | + # Print stats for the current function call |
| 46 | + print(f"{func.__name__}: Calls={performance.counter}, Time={time_taken:.4f}s, " |
| 47 | + f"Memory={peak / 1024:.1f}KB, TotalTime={performance.total_time:.4f}s, " |
| 48 | + f"TotalMem={performance.total_mem / 1024:.1f}KB") |
31 | 49 |
|
32 |
| - print(f"{func.__name__}: Calls={count}, Time={elapsed:.4f}s, " |
33 |
| - f"Memory={peak / 1024:.1f}KB, TotalTime={total_time:.4f}s, " |
34 |
| - f"TotalMem={total_mem / 1024:.1f}KB") |
| 50 | + return result |
35 | 51 |
|
36 | 52 | return wrapper
|
| 53 | + |
| 54 | + |
| 55 | +@performance |
| 56 | +def example_function(x): |
| 57 | + return x * x |
| 58 | + |
| 59 | + |
| 60 | +@performance |
| 61 | +def memory_intensive_function(size): |
| 62 | + return [0] * size |
| 63 | + |
| 64 | + |
| 65 | +if __name__ == "__main__": |
| 66 | + # Run test functions |
| 67 | + example_function(1) |
| 68 | + example_function(2) |
| 69 | + memory_intensive_function(1000000) |
| 70 | + |
| 71 | + # Display final performance metrics |
| 72 | + print(f"Function called {performance.counter} times.") |
| 73 | + print(f"Total time taken: {performance.total_time:.4f} seconds.") |
| 74 | + print(f"Total memory used: {performance.total_mem / 1024:.2f} KB.") |
0 commit comments