|
1 """Test suite for the profile module.""" |
|
2 |
|
3 import profile, pstats, sys |
|
4 |
|
5 # In order to have reproducible time, we simulate a timer in the global |
|
6 # variable 'ticks', which represents simulated time in milliseconds. |
|
7 # (We can't use a helper function increment the timer since it would be |
|
8 # included in the profile and would appear to consume all the time.) |
|
9 ticks = 0 |
|
10 |
|
11 # IMPORTANT: this is an output test. *ALL* NUMBERS in the expected |
|
12 # output are relevant. If you change the formatting of pstats, |
|
13 # please don't just regenerate output/test_profile without checking |
|
14 # very carefully that not a single number has changed. |
|
15 |
|
16 def test_main(): |
|
17 global ticks |
|
18 ticks = 42000 |
|
19 prof = profile.Profile(timer) |
|
20 prof.runctx("testfunc()", globals(), locals()) |
|
21 assert ticks == 43000, ticks |
|
22 st = pstats.Stats(prof) |
|
23 st.strip_dirs().sort_stats('stdname').print_stats() |
|
24 st.print_callees() |
|
25 st.print_callers() |
|
26 |
|
27 def timer(): |
|
28 return ticks*0.001 |
|
29 |
|
30 def testfunc(): |
|
31 # 1 call |
|
32 # 1000 ticks total: 270 ticks local, 730 ticks in subfunctions |
|
33 global ticks |
|
34 ticks += 99 |
|
35 helper() # 300 |
|
36 helper() # 300 |
|
37 ticks += 171 |
|
38 factorial(14) # 130 |
|
39 |
|
40 def factorial(n): |
|
41 # 23 calls total |
|
42 # 170 ticks total, 150 ticks local |
|
43 # 3 primitive calls, 130, 20 and 20 ticks total |
|
44 # including 116, 17, 17 ticks local |
|
45 global ticks |
|
46 if n > 0: |
|
47 ticks += n |
|
48 return mul(n, factorial(n-1)) |
|
49 else: |
|
50 ticks += 11 |
|
51 return 1 |
|
52 |
|
53 def mul(a, b): |
|
54 # 20 calls |
|
55 # 1 tick, local |
|
56 global ticks |
|
57 ticks += 1 |
|
58 return a * b |
|
59 |
|
60 def helper(): |
|
61 # 2 calls |
|
62 # 300 ticks total: 20 ticks local, 260 ticks in subfunctions |
|
63 global ticks |
|
64 ticks += 1 |
|
65 helper1() # 30 |
|
66 ticks += 2 |
|
67 helper1() # 30 |
|
68 ticks += 6 |
|
69 helper2() # 50 |
|
70 ticks += 3 |
|
71 helper2() # 50 |
|
72 ticks += 2 |
|
73 helper2() # 50 |
|
74 ticks += 5 |
|
75 helper2_indirect() # 70 |
|
76 ticks += 1 |
|
77 |
|
78 def helper1(): |
|
79 # 4 calls |
|
80 # 30 ticks total: 29 ticks local, 1 tick in subfunctions |
|
81 global ticks |
|
82 ticks += 10 |
|
83 hasattr(C(), "foo") # 1 |
|
84 ticks += 19 |
|
85 lst = [] |
|
86 lst.append(42) # 0 |
|
87 sys.exc_info() # 0 |
|
88 |
|
89 def helper2_indirect(): |
|
90 helper2() # 50 |
|
91 factorial(3) # 20 |
|
92 |
|
93 def helper2(): |
|
94 # 8 calls |
|
95 # 50 ticks local: 39 ticks local, 11 ticks in subfunctions |
|
96 global ticks |
|
97 ticks += 11 |
|
98 hasattr(C(), "bar") # 1 |
|
99 ticks += 13 |
|
100 subhelper() # 10 |
|
101 ticks += 15 |
|
102 |
|
103 def subhelper(): |
|
104 # 8 calls |
|
105 # 10 ticks total: 8 ticks local, 2 ticks in subfunctions |
|
106 global ticks |
|
107 ticks += 2 |
|
108 for i in range(2): # 0 |
|
109 try: |
|
110 C().foo # 1 x 2 |
|
111 except AttributeError: |
|
112 ticks += 3 # 3 x 2 |
|
113 |
|
114 class C: |
|
115 def __getattr__(self, name): |
|
116 # 28 calls |
|
117 # 1 tick, local |
|
118 global ticks |
|
119 ticks += 1 |
|
120 raise AttributeError |
|
121 |
|
122 if __name__ == "__main__": |
|
123 test_main() |