PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/_lsprof/test/test_cprofile.py

https://bitbucket.org/quangquach/pypy
Python | 284 lines | 265 code | 13 blank | 6 comment | 13 complexity | ce2db9d0788f3ed10bfc96af20666747 MD5 | raw file
  1. class AppTestCProfile(object):
  2. spaceconfig = {
  3. "usemodules": ['_lsprof', 'rctime'],
  4. }
  5. def setup_class(cls):
  6. cls.w_expected_output = cls.space.wrap(expected_output)
  7. cls.w_file = cls.space.wrap(__file__)
  8. def test_repr(self):
  9. import _lsprof
  10. assert repr(_lsprof.Profiler) == "<type '_lsprof.Profiler'>"
  11. def test_direct(self):
  12. import _lsprof
  13. def getticks():
  14. return len(ticks)
  15. prof = _lsprof.Profiler(getticks, 0.25, True, False)
  16. ticks = []
  17. def bar(m):
  18. ticks.append(1)
  19. if m == 1:
  20. foo(42)
  21. ticks.append(1)
  22. def spam(m):
  23. bar(m)
  24. def foo(n):
  25. bar(n)
  26. ticks.append(1)
  27. bar(n+1)
  28. ticks.append(1)
  29. spam(n+2)
  30. prof.enable()
  31. foo(0)
  32. prof.disable()
  33. assert len(ticks) == 16
  34. stats = prof.getstats()
  35. entries = {}
  36. for entry in stats:
  37. if not hasattr(entry.code, 'co_name'):
  38. print entry.code
  39. else:
  40. entries[entry.code.co_name] = entry
  41. efoo = entries['foo']
  42. assert efoo.callcount == 2
  43. assert efoo.reccallcount == 1
  44. assert efoo.inlinetime == 1.0
  45. assert efoo.totaltime == 4.0
  46. assert len(efoo.calls) == 2
  47. ebar = entries['bar']
  48. assert ebar.callcount == 6
  49. assert ebar.reccallcount == 3
  50. assert ebar.inlinetime == 3.0
  51. assert ebar.totaltime == 3.5
  52. assert len(ebar.calls) == 1
  53. espam = entries['spam']
  54. assert espam.callcount == 2
  55. assert espam.reccallcount == 0
  56. assert espam.inlinetime == 0.0
  57. assert espam.totaltime == 1.0
  58. assert len(espam.calls) == 1
  59. foo2spam, foo2bar = efoo.calls
  60. if foo2bar.code.co_name == 'spam':
  61. foo2bar, foo2spam = foo2spam, foo2bar
  62. assert foo2bar.code.co_name == 'bar'
  63. assert foo2bar.callcount == 4
  64. assert foo2bar.reccallcount == 2
  65. assert foo2bar.inlinetime == 2.0
  66. assert foo2bar.totaltime == 3.0
  67. assert foo2spam.code.co_name == 'spam'
  68. assert foo2spam.callcount == 2
  69. assert foo2spam.reccallcount == 0
  70. assert foo2spam.inlinetime == 0.0
  71. assert foo2spam.totaltime == 1.0
  72. bar2foo, = ebar.calls
  73. assert bar2foo.code.co_name == 'foo'
  74. assert bar2foo.callcount == 1
  75. assert bar2foo.reccallcount == 0
  76. assert bar2foo.inlinetime == 0.5
  77. assert bar2foo.totaltime == 2.0
  78. spam2bar, = espam.calls
  79. assert spam2bar.code.co_name == 'bar'
  80. assert spam2bar.callcount == 2
  81. assert spam2bar.reccallcount == 0
  82. assert spam2bar.inlinetime == 1.0
  83. assert spam2bar.totaltime == 1.0
  84. def test_scale_of_result(self):
  85. import _lsprof, time
  86. prof = _lsprof.Profiler()
  87. def foo(n):
  88. t = time.time()
  89. while abs(t - time.time()) < 1.0:
  90. pass # busy-wait for 1 second
  91. def bar(n):
  92. foo(n)
  93. prof.enable()
  94. bar(0)
  95. prof.disable()
  96. stats = prof.getstats()
  97. entries = {}
  98. for entry in stats:
  99. entries[entry.code] = entry
  100. efoo = entries[foo.func_code]
  101. ebar = entries[bar.func_code]
  102. assert 0.9 < efoo.totaltime < 2.9
  103. # --- cannot test .inlinetime, because it does not include
  104. # --- the time spent doing the call to time.time()
  105. #assert 0.9 < efoo.inlinetime < 2.9
  106. for subentry in ebar.calls:
  107. assert 0.9 < subentry.totaltime < 2.9
  108. #assert 0.9 < subentry.inlinetime < 2.9
  109. def test_builtin_exception(self):
  110. import math
  111. import _lsprof
  112. prof = _lsprof.Profiler()
  113. prof.enable()
  114. try:
  115. math.sqrt("a")
  116. except TypeError:
  117. pass
  118. prof.disable()
  119. stats = prof.getstats()
  120. assert len(stats) == 2
  121. def test_use_cprofile(self):
  122. import sys, os
  123. # XXX this is evil trickery to walk around the fact that we don't
  124. # have __file__ at app-level here
  125. sys.path.insert(0, os.path.dirname(self.file))
  126. try:
  127. import re
  128. from cProfile import Profile
  129. from profilee import testfunc, timer
  130. methodnames = ['print_stats', 'print_callers', 'print_callees']
  131. def do_profiling(cls):
  132. results = []
  133. prof = cls(timer, 0.001)
  134. start_timer = timer()
  135. prof.runctx("testfunc()", {'testfunc':testfunc}, locals())
  136. results.append(timer() - start_timer)
  137. for methodname in methodnames:
  138. import pstats
  139. from StringIO import StringIO
  140. s = StringIO()
  141. stats = pstats.Stats(prof, stream=s)
  142. stats.strip_dirs().sort_stats("stdname")
  143. getattr(stats, methodname)()
  144. results.append(s.getvalue())
  145. return results, prof
  146. res, prof = do_profiling(Profile)
  147. assert res[0] == 1000
  148. for i, method in enumerate(methodnames):
  149. got = res[i + 1]
  150. expected = self.expected_output[method]
  151. patterns = expected.splitlines()
  152. lines = set(got.splitlines())
  153. lines.remove('') # ignore blank lines
  154. for pattern in patterns:
  155. if not pattern:
  156. continue # ignore blank lines
  157. pattern = pattern.replace('(', '\\(')
  158. pattern = pattern.replace(')', '\\)')
  159. pattern = pattern.replace('?', '\\?')
  160. pattern = pattern.replace(r'\\?', '?')
  161. pattern = pattern.replace(r'\\(', '(')
  162. pattern = pattern.replace(r'\\)', ')')
  163. repattern = re.compile('^' + pattern + '$')
  164. for line in lines:
  165. if repattern.match(line):
  166. lines.remove(line)
  167. break
  168. else:
  169. print 'NOT FOUND:', pattern.rstrip('\n')
  170. print '--- GOT ---'
  171. print got
  172. print
  173. print '--- EXPECTED ---'
  174. print expected
  175. assert False
  176. assert not lines
  177. finally:
  178. sys.path.pop(0)
  179. class AppTestWithDifferentBytecodes(AppTestCProfile):
  180. spaceconfig = AppTestCProfile.spaceconfig.copy()
  181. spaceconfig['objspace.opcodes.CALL_METHOD'] = True
  182. expected_output = {}
  183. expected_output['print_stats'] = """\
  184. 126 function calls (106 primitive calls) in 1.000 seconds
  185. Ordered by: standard name
  186. ncalls tottime percall cumtime percall filename:lineno(function)
  187. 1 0.000 0.000 1.000 1.000 <string>:1(<module>)
  188. 28 0.028 0.001 0.028 0.001 profilee.py:110(__getattr__)
  189. 1 0.270 0.270 1.000 1.000 profilee.py:25(testfunc)
  190. 23/3 0.150 0.007 0.170 0.057 profilee.py:35(factorial)
  191. 20 0.020 0.001 0.020 0.001 profilee.py:48(mul)
  192. 2 0.040 0.020 0.600 0.300 profilee.py:55(helper)
  193. 4 0.116 0.029 0.120 0.030 profilee.py:73(helper1)
  194. 2 0.000 0.000 0.140 0.070 profilee.py:84(helper2_indirect)
  195. 8 0.312 0.039 0.400 0.050 profilee.py:88(helper2)
  196. 8 0.064 0.008 0.080 0.010 profilee.py:98(subhelper)
  197. 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
  198. 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
  199. 12 0.000 0.000 0.012 0.001 {hasattr}
  200. 8 0.000 0.000 0.000 0.000 {range}
  201. 4 0.000 0.000 0.000 0.000 {sys.exc_info}
  202. """
  203. expected_output['print_callers'] = """\
  204. Ordered by: standard name
  205. Function * was called by...
  206. * ncalls tottime cumtime
  207. <string>:1(<module>) * <-
  208. profilee.py:110(__getattr__) * <- 16 0.016 0.016 profilee.py:98(subhelper)
  209. * 12 0.012 0.012 {hasattr.*}
  210. profilee.py:25(testfunc) * <- 1 0.270 1.000 <string>:1(<module>)
  211. profilee.py:35(factorial) * <- 1 0.014 0.130 profilee.py:25(testfunc)
  212. * 20/3 0.130 0.147 profilee.py:35(factorial)
  213. * 2 0.006 0.040 profilee.py:84(helper2_indirect)
  214. profilee.py:48(mul) * <- 20 0.020 0.020 profilee.py:35(factorial)
  215. profilee.py:55(helper) * <- 2 0.040 0.600 profilee.py:25(testfunc)
  216. profilee.py:73(helper1) * <- 4 0.116 0.120 profilee.py:55(helper)
  217. profilee.py:84(helper2_indirect) *<- 2 0.000 0.140 profilee.py:55(helper)
  218. profilee.py:88(helper2) * <- 6 0.234 0.300 profilee.py:55(helper)
  219. * 2 0.078 0.100 profilee.py:84(helper2_indirect)
  220. profilee.py:98(subhelper) * <- 8 0.064 0.080 profilee.py:88(helper2)
  221. {.*append.*} * <- 4 0.000 0.000 profilee.py:73(helper1)
  222. {.*disable.*} * <-
  223. {hasattr.*} * <- 4 0.000 0.004 profilee.py:73(helper1)
  224. * 8 0.000 0.008 profilee.py:88(helper2)
  225. {range.*} * <- 8 0.000 0.000 profilee.py:98(subhelper)
  226. {sys.exc_info.*} * <- 4 0.000 0.000 profilee.py:73(helper1)
  227. """
  228. expected_output['print_callees'] = """\
  229. Ordered by: standard name
  230. Function * called...
  231. * ncalls tottime cumtime
  232. <string>:1(<module>) * -> 1 0.270 1.000 profilee.py:25(testfunc)
  233. profilee.py:110(__getattr__) * ->
  234. profilee.py:25(testfunc) * -> 1 0.014 0.130 profilee.py:35(factorial)
  235. * 2 0.040 0.600 profilee.py:55(helper)
  236. profilee.py:35(factorial) * -> 20/3 0.130 0.147 profilee.py:35(factorial)
  237. * 20 0.020 0.020 profilee.py:48(mul)
  238. profilee.py:48(mul) * ->
  239. profilee.py:55(helper) * -> 4 0.116 0.120 profilee.py:73(helper1)
  240. * 2 0.000 0.140 profilee.py:84(helper2_indirect)
  241. * 6 0.234 0.300 profilee.py:88(helper2)
  242. \\(profilee.py:73(helper1)\\)\\? * .. 4 0.000 0.000 {.*append.*}
  243. \\(profilee.py:73(helper1)\\)\\? * .. 4 0.000 0.004 {.*hasattr.*}
  244. * 4 0.000 0.000 {sys.exc_info.*}
  245. profilee.py:84(helper2_indirect) * -> 2 0.006 0.040 profilee.py:35(factorial)
  246. * 2 0.078 0.100 profilee.py:88(helper2)
  247. profilee.py:88(helper2) * -> 8 0.064 0.080 profilee.py:98(subhelper)
  248. * 8 0.000 0.008 {hasattr.*}
  249. profilee.py:98(subhelper) * -> 16 0.016 0.016 profilee.py:110(__getattr__)
  250. * 8 0.000 0.000 {range.*}
  251. {.*append.*} * ->
  252. {.*disable.*} * ->
  253. {hasattr.*} * -> 12 0.012 0.012 profilee.py:110(__getattr__)
  254. {range.*} * ->
  255. {sys.exc_info.*} * ->
  256. """