blob: fa58897e68bd31bccd25abeb8adf795adefd48f3 [file] [log] [blame]
Andrew Geissler69721092021-07-23 12:57:00 -04001From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001
2From: Trevor Gamblin <trevor.gamblin@windriver.com>
3Date: Mon, 7 Jun 2021 09:40:20 -0400
4Subject: [PATCH] Fix imports for tests
5
6Signed-off-by: Trevor Gamblin <trevor.gamblin@windriver.com>
7---
8 tests/test_asyncio.py | 2 +-
9 tests/test_asyncio_context_vars.py | 2 +-
10 tests/test_functionality.py | 2 +-
11 tests/test_gevent.py | 2 +-
12 tests/test_hooks.py | 2 +-
13 tests/test_tags.py | 2 +-
14 6 files changed, 6 insertions(+), 6 deletions(-)
15
16--- a/tests/test_asyncio.py
17+++ b/tests/test_asyncio.py
18@@ -2,7 +2,7 @@ import unittest
19 import yappi
20 import asyncio
21 import threading
22-from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
23+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
24
25
26 @asyncio.coroutine
27--- a/tests/test_asyncio_context_vars.py
28+++ b/tests/test_asyncio_context_vars.py
29@@ -5,7 +5,7 @@ import contextvars
30 import functools
31 import time
32 import os
33-import utils
34+import tests.utils as utils
35 import yappi
36
37 async_context_id = contextvars.ContextVar('async_context_id')
38--- a/tests/test_functionality.py
39+++ b/tests/test_functionality.py
40@@ -1,1916 +1,1916 @@
41-import os
42-import sys
43-import time
44-import threading
45-import unittest
46-import yappi
47-import _yappi
48-import utils
49-import multiprocessing # added to fix http://bugs.python.org/issue15881 for > Py2.6
50-import subprocess
51-
52-_counter = 0
53-
54-
55-class BasicUsage(utils.YappiUnitTestCase):
56-
57- def test_callback_function_int_return_overflow(self):
58- # this test is just here to check if any errors are generated, as the err
59- # is printed in C side, I did not include it here. THere are ways to test
60- # this deterministically, I did not bother
61- import ctypes
62-
63- def _unsigned_overflow_margin():
64- return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
65-
66- def foo():
67- pass
68-
69- #with utils.captured_output() as (out, err):
70- yappi.set_context_id_callback(_unsigned_overflow_margin)
71- yappi.set_tag_callback(_unsigned_overflow_margin)
72- yappi.start()
73- foo()
74-
75- def test_issue60(self):
76-
77- def foo():
78- buf = bytearray()
79- buf += b't' * 200
80- view = memoryview(buf)[10:]
81- view = view.tobytes()
82- del buf[:10] # this throws exception
83- return view
84-
85- yappi.start(builtins=True)
86- foo()
87- self.assertTrue(
88- len(
89- yappi.get_func_stats(
90- filter_callback=lambda x: yappi.
91- func_matches(x, [memoryview.tobytes])
92- )
93- ) > 0
94- )
95- yappi.stop()
96-
97- def test_issue54(self):
98-
99- def _tag_cbk():
100- global _counter
101- _counter += 1
102- return _counter
103-
104- def a():
105- pass
106-
107- def b():
108- pass
109-
110- yappi.set_tag_callback(_tag_cbk)
111- yappi.start()
112- a()
113- a()
114- a()
115- yappi.stop()
116- stats = yappi.get_func_stats()
117- self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given
118- stats = yappi.get_func_stats(tag=1)
119-
120- for i in range(1, 3):
121- stats = yappi.get_func_stats(tag=i)
122- stats = yappi.get_func_stats(
123- tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
124- )
125-
126- stat = stats.pop()
127- self.assertEqual(stat.ncall, 1)
128-
129- yappi.set_tag_callback(None)
130- yappi.clear_stats()
131- yappi.start()
132- b()
133- b()
134- stats = yappi.get_func_stats()
135- self.assertEqual(len(stats), 1)
136- stat = stats.pop()
137- self.assertEqual(stat.ncall, 2)
138-
139- def test_filter(self):
140-
141- def a():
142- pass
143-
144- def b():
145- a()
146-
147- def c():
148- b()
149-
150- _TCOUNT = 5
151-
152- ts = []
153- yappi.start()
154- for i in range(_TCOUNT):
155- t = threading.Thread(target=c)
156- t.start()
157- ts.append(t)
158-
159- for t in ts:
160- t.join()
161-
162- yappi.stop()
163-
164- ctx_ids = []
165- for tstat in yappi.get_thread_stats():
166- if tstat.name == '_MainThread':
167- main_ctx_id = tstat.id
168- else:
169- ctx_ids.append(tstat.id)
170-
171- fstats = yappi.get_func_stats(filter={"ctx_id": 9})
172- self.assertTrue(fstats.empty())
173- fstats = yappi.get_func_stats(
174- filter={
175- "ctx_id": main_ctx_id,
176- "name": "c"
177- }
178- ) # main thread
179- self.assertTrue(fstats.empty())
180-
181- for i in ctx_ids:
182- fstats = yappi.get_func_stats(
183- filter={
184- "ctx_id": i,
185- "name": "a",
186- "ncall": 1
187- }
188- )
189- self.assertEqual(fstats.pop().ncall, 1)
190- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
191- self.assertEqual(fstats.pop().ncall, 1)
192- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
193- self.assertEqual(fstats.pop().ncall, 1)
194-
195- yappi.clear_stats()
196- yappi.start(builtins=True)
197- time.sleep(0.1)
198- yappi.stop()
199- fstats = yappi.get_func_stats(filter={"module": "time"})
200- self.assertEqual(len(fstats), 1)
201-
202- # invalid filters`
203- self.assertRaises(
204- Exception, yappi.get_func_stats, filter={'tag': "sss"}
205- )
206- self.assertRaises(
207- Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
208- )
209-
210- def test_filter_callback(self):
211-
212- def a():
213- time.sleep(0.1)
214-
215- def b():
216- a()
217-
218- def c():
219- pass
220-
221- def d():
222- pass
223-
224- yappi.set_clock_type("wall")
225- yappi.start(builtins=True)
226- a()
227- b()
228- c()
229- d()
230- stats = yappi.get_func_stats(
231- filter_callback=lambda x: yappi.func_matches(x, [a, b])
232- )
233- #stats.print_all()
234- r1 = '''
235- tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175
236- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197
237- '''
238- self.assert_traces_almost_equal(r1, stats)
239- self.assertEqual(len(stats), 2)
240- stats = yappi.get_func_stats(
241- filter_callback=lambda x: yappi.
242- module_matches(x, [sys.modules[__name__]])
243- )
244- r1 = '''
245- tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065
246- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011
247- tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002
248- tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001
249- '''
250- self.assert_traces_almost_equal(r1, stats)
251- self.assertEqual(len(stats), 4)
252-
253- stats = yappi.get_func_stats(
254- filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
255- )
256- self.assertEqual(len(stats), 1)
257- r1 = '''
258- time.sleep 2 0.206804 0.220000 0.103402
259- '''
260- self.assert_traces_almost_equal(r1, stats)
261-
262- def test_print_formatting(self):
263-
264- def a():
265- pass
266-
267- def b():
268- a()
269-
270- func_cols = {
271- 1: ("name", 48),
272- 0: ("ncall", 5),
273- 2: ("tsub", 8),
274- }
275- thread_cols = {
276- 1: ("name", 48),
277- 0: ("ttot", 8),
278- }
279-
280- yappi.start()
281- a()
282- b()
283- yappi.stop()
284- fs = yappi.get_func_stats()
285- cs = fs[1].children
286- ts = yappi.get_thread_stats()
287- #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
288- #cs.print_all(out=sys.stderr, columns=func_cols)
289- #ts.print_all(out=sys.stderr, columns=thread_cols)
290- #cs.print_all(out=sys.stderr, columns={})
291-
292- self.assertRaises(
293- yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
294- )
295- self.assertRaises(
296- yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
297- )
298- self.assertRaises(
299- yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
300- )
301-
302- def test_get_clock(self):
303- yappi.set_clock_type('cpu')
304- self.assertEqual('cpu', yappi.get_clock_type())
305- clock_info = yappi.get_clock_info()
306- self.assertTrue('api' in clock_info)
307- self.assertTrue('resolution' in clock_info)
308-
309- yappi.set_clock_type('wall')
310- self.assertEqual('wall', yappi.get_clock_type())
311-
312- t0 = yappi.get_clock_time()
313- time.sleep(0.1)
314- duration = yappi.get_clock_time() - t0
315- self.assertTrue(0.05 < duration < 0.3)
316-
317- def test_profile_decorator(self):
318-
319- def aggregate(func, stats):
320- fname = "tests/%s.profile" % (func.__name__)
321- try:
322- stats.add(fname)
323- except IOError:
324- pass
325- stats.save(fname)
326- raise Exception("messing around")
327-
328- @yappi.profile(return_callback=aggregate)
329- def a(x, y):
330- if x + y == 25:
331- raise Exception("")
332- return x + y
333-
334- def b():
335- pass
336-
337- try:
338- os.remove(
339- "tests/a.profile"
340- ) # remove the one from prev test, if available
341- except:
342- pass
343-
344- # global profile is on to mess things up
345- yappi.start()
346- b()
347-
348- # assert functionality and call function at same time
349- try:
350- self.assertEqual(a(1, 2), 3)
351- except:
352- pass
353- try:
354- self.assertEqual(a(2, 5), 7)
355- except:
356- pass
357- try:
358- a(4, 21)
359- except:
360- pass
361- stats = yappi.get_func_stats().add("tests/a.profile")
362- fsa = utils.find_stat_by_name(stats, 'a')
363- self.assertEqual(fsa.ncall, 3)
364- self.assertEqual(len(stats), 1) # b() should be cleared out.
365-
366- @yappi.profile(return_callback=aggregate)
367- def count_down_rec(n):
368- if n == 0:
369- return
370- count_down_rec(n - 1)
371-
372- try:
373- os.remove(
374- "tests/count_down_rec.profile"
375- ) # remove the one from prev test, if available
376- except:
377- pass
378-
379- try:
380- count_down_rec(4)
381- except:
382- pass
383- try:
384- count_down_rec(3)
385- except:
386- pass
387-
388- stats = yappi.YFuncStats("tests/count_down_rec.profile")
389- fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
390- self.assertEqual(fsrec.ncall, 9)
391- self.assertEqual(fsrec.nactualcall, 2)
392-
393- def test_strip_dirs(self):
394-
395- def a():
396- pass
397-
398- stats = utils.run_and_get_func_stats(a, )
399- stats.strip_dirs()
400- fsa = utils.find_stat_by_name(stats, "a")
401- self.assertEqual(fsa.module, os.path.basename(fsa.module))
402-
403- @unittest.skipIf(os.name == "nt", "do not run on Windows")
404- def test_run_as_script(self):
405- import re
406- p = subprocess.Popen(
407- ['yappi', os.path.join('./tests', 'run_as_script.py')],
408- stdout=subprocess.PIPE
409- )
410- out, err = p.communicate()
411- self.assertEqual(p.returncode, 0)
412- func_stats, thread_stats = re.split(
413- b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
414- )
415- self.assertTrue(b'FancyThread' in thread_stats)
416-
417- def test_yappi_overhead(self):
418- LOOP_COUNT = 100000
419-
420- def a():
421- pass
422-
423- def b():
424- for i in range(LOOP_COUNT):
425- a()
426-
427- t0 = time.time()
428- yappi.start()
429- b()
430- yappi.stop()
431- time_with_yappi = time.time() - t0
432- t0 = time.time()
433- b()
434- time_without_yappi = time.time() - t0
435- if time_without_yappi == 0:
436- time_without_yappi = 0.000001
437-
438- # in latest v0.82, I calculated this as close to "7.0" in my machine.
439- # however, %83 of this overhead is coming from tickcount(). The other %17
440- # seems to have been evenly distributed to the internal bookkeeping
441- # structures/algorithms which seems acceptable. Note that our test only
442- # tests one function being profiled at-a-time in a short interval.
443- # profiling high number of functions in a small time
444- # is a different beast, (which is pretty unlikely in most applications)
445- # So as a conclusion: I cannot see any optimization window for Yappi that
446- # is worth implementing as we will only optimize %17 of the time.
447- sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
448- (time_with_yappi / time_without_yappi))
449-
450- def test_clear_stats_while_running(self):
451-
452- def a():
453- pass
454-
455- yappi.start()
456- a()
457- yappi.clear_stats()
458- a()
459- stats = yappi.get_func_stats()
460- fsa = utils.find_stat_by_name(stats, 'a')
461- self.assertEqual(fsa.ncall, 1)
462-
463- def test_generator(self):
464-
465- def _gen(n):
466- while (n > 0):
467- yield n
468- n -= 1
469-
470- yappi.start()
471- for x in _gen(5):
472- pass
473- self.assertTrue(
474- yappi.convert2pstats(yappi.get_func_stats()) is not None
475- )
476-
477- def test_slice_child_stats_and_strip_dirs(self):
478-
479- def b():
480- for i in range(10000000):
481- pass
482-
483- def a():
484- b()
485-
486- yappi.start(builtins=True)
487- a()
488- stats = yappi.get_func_stats()
489- fsa = utils.find_stat_by_name(stats, 'a')
490- fsb = utils.find_stat_by_name(stats, 'b')
491- self.assertTrue(fsa.children[0:1] is not None)
492- prev_afullname = fsa.full_name
493- prev_bchildfullname = fsa.children[fsb].full_name
494- stats.strip_dirs()
495- self.assertTrue(len(prev_afullname) > len(fsa.full_name))
496- self.assertTrue(
497- len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
498- )
499-
500- def test_children_stat_functions(self):
501- _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
502- _yappi._set_test_timings(_timings)
503-
504- def b():
505- pass
506-
507- def c():
508- pass
509-
510- def a():
511- b()
512- c()
513-
514- yappi.start()
515- a()
516- b() # non-child call
517- c() # non-child call
518- stats = yappi.get_func_stats()
519- fsa = utils.find_stat_by_name(stats, 'a')
520- childs_of_a = fsa.children.get().sort("tavg", "desc")
521- prev_item = None
522- for item in childs_of_a:
523- if prev_item:
524- self.assertTrue(prev_item.tavg > item.tavg)
525- prev_item = item
526- childs_of_a.sort("name", "desc")
527- prev_item = None
528- for item in childs_of_a:
529- if prev_item:
530- self.assertTrue(prev_item.name > item.name)
531- prev_item = item
532- childs_of_a.clear()
533- self.assertTrue(childs_of_a.empty())
534-
535- def test_no_stats_different_clock_type_load(self):
536-
537- def a():
538- pass
539-
540- yappi.start()
541- a()
542- yappi.stop()
543- yappi.get_func_stats().save("tests/ystats1.ys")
544- yappi.clear_stats()
545- yappi.set_clock_type("WALL")
546- yappi.start()
547- yappi.stop()
548- stats = yappi.get_func_stats().add("tests/ystats1.ys")
549- fsa = utils.find_stat_by_name(stats, 'a')
550- self.assertTrue(fsa is not None)
551-
552- def test_subsequent_profile(self):
553- _timings = {"a_1": 1, "b_1": 1}
554- _yappi._set_test_timings(_timings)
555-
556- def a():
557- pass
558-
559- def b():
560- pass
561-
562- yappi.start()
563- a()
564- yappi.stop()
565- yappi.start()
566- b()
567- yappi.stop()
568- stats = yappi.get_func_stats()
569- fsa = utils.find_stat_by_name(stats, 'a')
570- fsb = utils.find_stat_by_name(stats, 'b')
571- self.assertTrue(fsa is not None)
572- self.assertTrue(fsb is not None)
573- self.assertEqual(fsa.ttot, 1)
574- self.assertEqual(fsb.ttot, 1)
575-
576- def test_lambda(self):
577- f = lambda: time.sleep(0.3)
578- yappi.set_clock_type("wall")
579- yappi.start()
580- f()
581- stats = yappi.get_func_stats()
582- fsa = utils.find_stat_by_name(stats, '<lambda>')
583- self.assertTrue(fsa.ttot > 0.1)
584-
585- def test_module_stress(self):
586- self.assertEqual(yappi.is_running(), False)
587-
588- yappi.start()
589- yappi.clear_stats()
590- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
591-
592- yappi.stop()
593- yappi.clear_stats()
594- yappi.set_clock_type("cpu")
595- self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
596- self.assertEqual(yappi.is_running(), False)
597- yappi.clear_stats()
598- yappi.clear_stats()
599-
600- def test_stat_sorting(self):
601- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
602- _yappi._set_test_timings(_timings)
603-
604- self._ncall = 1
605-
606- def a():
607- b()
608-
609- def b():
610- if self._ncall == 2:
611- return
612- self._ncall += 1
613- a()
614-
615- stats = utils.run_and_get_func_stats(a)
616- stats = stats.sort("totaltime", "desc")
617- prev_stat = None
618- for stat in stats:
619- if prev_stat:
620- self.assertTrue(prev_stat.ttot >= stat.ttot)
621- prev_stat = stat
622- stats = stats.sort("totaltime", "asc")
623- prev_stat = None
624- for stat in stats:
625- if prev_stat:
626- self.assertTrue(prev_stat.ttot <= stat.ttot)
627- prev_stat = stat
628- stats = stats.sort("avgtime", "asc")
629- prev_stat = None
630- for stat in stats:
631- if prev_stat:
632- self.assertTrue(prev_stat.tavg <= stat.tavg)
633- prev_stat = stat
634- stats = stats.sort("name", "asc")
635- prev_stat = None
636- for stat in stats:
637- if prev_stat:
638- self.assertTrue(prev_stat.name <= stat.name)
639- prev_stat = stat
640- stats = stats.sort("subtime", "asc")
641- prev_stat = None
642- for stat in stats:
643- if prev_stat:
644- self.assertTrue(prev_stat.tsub <= stat.tsub)
645- prev_stat = stat
646-
647- self.assertRaises(
648- yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
649- )
650- self.assertRaises(
651- yappi.YappiError, stats.sort, "totaltime",
652- "invalid_func_sortorder_arg"
653- )
654-
655- def test_start_flags(self):
656- self.assertEqual(_yappi._get_start_flags(), None)
657- yappi.start()
658-
659- def a():
660- pass
661-
662- a()
663- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
664- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
665- self.assertEqual(len(yappi.get_thread_stats()), 1)
666-
667- def test_builtin_profiling(self):
668-
669- def a():
670- time.sleep(0.4) # is a builtin function
671-
672- yappi.set_clock_type('wall')
673-
674- yappi.start(builtins=True)
675- a()
676- stats = yappi.get_func_stats()
677- fsa = utils.find_stat_by_name(stats, 'sleep')
678- self.assertTrue(fsa is not None)
679- self.assertTrue(fsa.ttot > 0.3)
680- yappi.stop()
681- yappi.clear_stats()
682-
683- def a():
684- pass
685-
686- yappi.start()
687- t = threading.Thread(target=a)
688- t.start()
689- t.join()
690- stats = yappi.get_func_stats()
691-
692- def test_singlethread_profiling(self):
693- yappi.set_clock_type('wall')
694-
695- def a():
696- time.sleep(0.2)
697-
698- class Worker1(threading.Thread):
699-
700- def a(self):
701- time.sleep(0.3)
702-
703- def run(self):
704- self.a()
705-
706- yappi.start(profile_threads=False)
707-
708- c = Worker1()
709- c.start()
710- c.join()
711- a()
712- stats = yappi.get_func_stats()
713- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
714- fsa2 = utils.find_stat_by_name(stats, 'a')
715- self.assertTrue(fsa1 is None)
716- self.assertTrue(fsa2 is not None)
717- self.assertTrue(fsa2.ttot > 0.1)
718-
719- def test_run(self):
720-
721- def profiled():
722- pass
723-
724- yappi.clear_stats()
725- try:
726- with yappi.run():
727- profiled()
728- stats = yappi.get_func_stats()
729- finally:
730- yappi.clear_stats()
731-
732- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
733-
734- def test_run_recursive(self):
735-
736- def profiled():
737- pass
738-
739- def not_profiled():
740- pass
741-
742- yappi.clear_stats()
743- try:
744- with yappi.run():
745- with yappi.run():
746- profiled()
747- # Profiling stopped here
748- not_profiled()
749- stats = yappi.get_func_stats()
750- finally:
751- yappi.clear_stats()
752-
753- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
754- self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
755-
756-
757-class StatSaveScenarios(utils.YappiUnitTestCase):
758-
759- def test_pstats_conversion(self):
760-
761- def pstat_id(fs):
762- return (fs.module, fs.lineno, fs.name)
763-
764- def a():
765- d()
766-
767- def b():
768- d()
769-
770- def c():
771- pass
772-
773- def d():
774- pass
775-
776- _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
777- _yappi._set_test_timings(_timings)
778- stats = utils.run_and_get_func_stats(a, )
779- stats.strip_dirs()
780- stats.save("tests/a1.pstats", type="pstat")
781- fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
782- fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
783- yappi.clear_stats()
784- _yappi._set_test_timings(_timings)
785- stats = utils.run_and_get_func_stats(a, )
786- stats.strip_dirs()
787- stats.save("tests/a2.pstats", type="pstat")
788- yappi.clear_stats()
789- _yappi._set_test_timings(_timings)
790- stats = utils.run_and_get_func_stats(b, )
791- stats.strip_dirs()
792- stats.save("tests/b1.pstats", type="pstat")
793- fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
794- yappi.clear_stats()
795- _yappi._set_test_timings(_timings)
796- stats = utils.run_and_get_func_stats(c, )
797- stats.strip_dirs()
798- stats.save("tests/c1.pstats", type="pstat")
799- fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
800-
801- # merge saved stats and check pstats values are correct
802- import pstats
803- p = pstats.Stats(
804- 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
805- 'tests/c1.pstats'
806- )
807- p.strip_dirs()
808- # ct = ttot, tt = tsub
809- (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
810- self.assertEqual(cc, nc, 2)
811- self.assertEqual(tt, 20)
812- self.assertEqual(ct, 24)
813- (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
814- self.assertEqual(cc, nc, 3)
815- self.assertEqual(tt, 6)
816- self.assertEqual(ct, 6)
817- self.assertEqual(len(callers), 2)
818- (cc, nc, tt, ct) = callers[fsa_pid]
819- self.assertEqual(cc, nc, 2)
820- self.assertEqual(tt, 4)
821- self.assertEqual(ct, 4)
822- (cc, nc, tt, ct) = callers[fsb_pid]
823- self.assertEqual(cc, nc, 1)
824- self.assertEqual(tt, 2)
825- self.assertEqual(ct, 2)
826-
827- def test_merge_stats(self):
828- _timings = {
829- "a_1": 15,
830- "b_1": 14,
831- "c_1": 12,
832- "d_1": 10,
833- "e_1": 9,
834- "f_1": 7,
835- "g_1": 6,
836- "h_1": 5,
837- "i_1": 1
838- }
839- _yappi._set_test_timings(_timings)
840-
841- def a():
842- b()
843-
844- def b():
845- c()
846-
847- def c():
848- d()
849-
850- def d():
851- e()
852-
853- def e():
854- f()
855-
856- def f():
857- g()
858-
859- def g():
860- h()
861-
862- def h():
863- i()
864-
865- def i():
866- pass
867-
868- yappi.start()
869- a()
870- a()
871- yappi.stop()
872- stats = yappi.get_func_stats()
873- self.assertRaises(
874- NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
875- )
876- stats.save("tests/ystats2.ys")
877- yappi.clear_stats()
878- _yappi._set_test_timings(_timings)
879- yappi.start()
880- a()
881- stats = yappi.get_func_stats().add("tests/ystats2.ys")
882- fsa = utils.find_stat_by_name(stats, "a")
883- fsb = utils.find_stat_by_name(stats, "b")
884- fsc = utils.find_stat_by_name(stats, "c")
885- fsd = utils.find_stat_by_name(stats, "d")
886- fse = utils.find_stat_by_name(stats, "e")
887- fsf = utils.find_stat_by_name(stats, "f")
888- fsg = utils.find_stat_by_name(stats, "g")
889- fsh = utils.find_stat_by_name(stats, "h")
890- fsi = utils.find_stat_by_name(stats, "i")
891- self.assertEqual(fsa.ttot, 45)
892- self.assertEqual(fsa.ncall, 3)
893- self.assertEqual(fsa.nactualcall, 3)
894- self.assertEqual(fsa.tsub, 3)
895- self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
896- self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
897- self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
898- self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
899- self.assertEqual(fsc.tsub, 6)
900- self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
901- self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
902- self.assertEqual(fsd.children[fse].ttot, fse.ttot)
903- self.assertEqual(fsd.children[fse].tsub, fse.tsub)
904- self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
905- self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
906- self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
907- self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
908- self.assertEqual(fsg.ttot, 18)
909- self.assertEqual(fsg.tsub, 3)
910- self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
911- self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
912- self.assertEqual(fsh.ttot, 15)
913- self.assertEqual(fsh.tsub, 12)
914- self.assertEqual(fsh.tavg, 5)
915- self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
916- self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
917- #stats.debug_print()
918-
919- def test_merge_multithreaded_stats(self):
920- import _yappi
921- timings = {"a_1": 2, "b_1": 1}
922- _yappi._set_test_timings(timings)
923-
924- def a():
925- pass
926-
927- def b():
928- pass
929-
930- yappi.start()
931- t = threading.Thread(target=a)
932- t.start()
933- t.join()
934- t = threading.Thread(target=b)
935- t.start()
936- t.join()
937- yappi.get_func_stats().save("tests/ystats1.ys")
938- yappi.clear_stats()
939- _yappi._set_test_timings(timings)
940- self.assertEqual(len(yappi.get_func_stats()), 0)
941- self.assertEqual(len(yappi.get_thread_stats()), 1)
942- t = threading.Thread(target=a)
943- t.start()
944- t.join()
945-
946- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
947- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
948- yappi.get_func_stats().save("tests/ystats2.ys")
949-
950- stats = yappi.YFuncStats([
951- "tests/ystats1.ys",
952- "tests/ystats2.ys",
953- ])
954- fsa = utils.find_stat_by_name(stats, "a")
955- fsb = utils.find_stat_by_name(stats, "b")
956- self.assertEqual(fsa.ncall, 2)
957- self.assertEqual(fsb.ncall, 1)
958- self.assertEqual(fsa.tsub, fsa.ttot, 4)
959- self.assertEqual(fsb.tsub, fsb.ttot, 1)
960-
961- def test_merge_load_different_clock_types(self):
962- yappi.start(builtins=True)
963-
964- def a():
965- b()
966-
967- def b():
968- c()
969-
970- def c():
971- pass
972-
973- t = threading.Thread(target=a)
974- t.start()
975- t.join()
976- yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
977- yappi.stop()
978- yappi.clear_stats()
979- yappi.start(builtins=False)
980- t = threading.Thread(target=a)
981- t.start()
982- t.join()
983- yappi.get_func_stats().save("tests/ystats2.ys")
984- yappi.stop()
985- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
986- yappi.clear_stats()
987- yappi.set_clock_type("wall")
988- yappi.start()
989- t = threading.Thread(target=a)
990- t.start()
991- t.join()
992- yappi.get_func_stats().save("tests/ystats3.ys")
993- self.assertRaises(
994- yappi.YappiError,
995- yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
996- )
997- stats = yappi.YFuncStats(["tests/ystats1.ys",
998- "tests/ystats2.ys"]).sort("name")
999- fsa = utils.find_stat_by_name(stats, "a")
1000- fsb = utils.find_stat_by_name(stats, "b")
1001- fsc = utils.find_stat_by_name(stats, "c")
1002- self.assertEqual(fsa.ncall, 2)
1003- self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
1004-
1005- def test_merge_aabab_aabbc(self):
1006- _timings = {
1007- "a_1": 15,
1008- "a_2": 14,
1009- "b_1": 12,
1010- "a_3": 10,
1011- "b_2": 9,
1012- "c_1": 4
1013- }
1014- _yappi._set_test_timings(_timings)
1015-
1016- def a():
1017- if self._ncall == 1:
1018- self._ncall += 1
1019- a()
1020- elif self._ncall == 5:
1021- self._ncall += 1
1022- a()
1023- else:
1024- b()
1025-
1026- def b():
1027- if self._ncall == 2:
1028- self._ncall += 1
1029- a()
1030- elif self._ncall == 6:
1031- self._ncall += 1
1032- b()
1033- elif self._ncall == 7:
1034- c()
1035- else:
1036- return
1037-
1038- def c():
1039- pass
1040-
1041- self._ncall = 1
1042- stats = utils.run_and_get_func_stats(a, )
1043- stats.save("tests/ystats1.ys")
1044- yappi.clear_stats()
1045- _yappi._set_test_timings(_timings)
1046- #stats.print_all()
1047-
1048- self._ncall = 5
1049- stats = utils.run_and_get_func_stats(a, )
1050- stats.save("tests/ystats2.ys")
1051-
1052- #stats.print_all()
1053-
1054- def a(): # same name but another function(code object)
1055- pass
1056-
1057- yappi.start()
1058- a()
1059- stats = yappi.get_func_stats().add(
1060- ["tests/ystats1.ys", "tests/ystats2.ys"]
1061- )
1062- #stats.print_all()
1063- self.assertEqual(len(stats), 4)
1064-
1065- fsa = None
1066- for stat in stats:
1067- if stat.name == "a" and stat.ttot == 45:
1068- fsa = stat
1069- break
1070- self.assertTrue(fsa is not None)
1071-
1072- self.assertEqual(fsa.ncall, 7)
1073- self.assertEqual(fsa.nactualcall, 3)
1074- self.assertEqual(fsa.ttot, 45)
1075- self.assertEqual(fsa.tsub, 10)
1076- fsb = utils.find_stat_by_name(stats, "b")
1077- fsc = utils.find_stat_by_name(stats, "c")
1078- self.assertEqual(fsb.ncall, 6)
1079- self.assertEqual(fsb.nactualcall, 3)
1080- self.assertEqual(fsb.ttot, 36)
1081- self.assertEqual(fsb.tsub, 27)
1082- self.assertEqual(fsb.tavg, 6)
1083- self.assertEqual(fsc.ttot, 8)
1084- self.assertEqual(fsc.tsub, 8)
1085- self.assertEqual(fsc.tavg, 4)
1086- self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
1087-
1088-
1089-class MultithreadedScenarios(utils.YappiUnitTestCase):
1090-
1091- def test_issue_32(self):
1092- '''
1093- Start yappi from different thread and we get Internal Error(15) as
1094- the current_ctx_id() called while enumerating the threads in start()
1095- and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
1096- returns wrong object and thus sets an invalid id for the _ctx structure.
1097-
1098- When this issue happens multiple Threads have same tid as the internal ts_ptr
1099- will be same for different contexts. So, let's see if that happens
1100- '''
1101-
1102- def foo():
1103- time.sleep(0.2)
1104-
1105- def bar():
1106- time.sleep(0.1)
1107-
1108- def thread_func():
1109- yappi.set_clock_type("wall")
1110- yappi.start()
1111-
1112- bar()
1113-
1114- t = threading.Thread(target=thread_func)
1115- t.start()
1116- t.join()
1117-
1118- foo()
1119-
1120- yappi.stop()
1121-
1122- thread_ids = set()
1123- for tstat in yappi.get_thread_stats():
1124- self.assertTrue(tstat.tid not in thread_ids)
1125- thread_ids.add(tstat.tid)
1126-
1127- def test_subsequent_profile(self):
1128- WORKER_COUNT = 5
1129-
1130- def a():
1131- pass
1132-
1133- def b():
1134- pass
1135-
1136- def c():
1137- pass
1138-
1139- _timings = {
1140- "a_1": 3,
1141- "b_1": 2,
1142- "c_1": 1,
1143- }
1144-
1145- yappi.start()
1146-
1147- def g():
1148- pass
1149-
1150- g()
1151- yappi.stop()
1152- yappi.clear_stats()
1153- _yappi._set_test_timings(_timings)
1154- yappi.start()
1155-
1156- _dummy = []
1157- for i in range(WORKER_COUNT):
1158- t = threading.Thread(target=a)
1159- t.start()
1160- t.join()
1161- for i in range(WORKER_COUNT):
1162- t = threading.Thread(target=b)
1163- t.start()
1164- _dummy.append(t)
1165- t.join()
1166- for i in range(WORKER_COUNT):
1167- t = threading.Thread(target=a)
1168- t.start()
1169- t.join()
1170- for i in range(WORKER_COUNT):
1171- t = threading.Thread(target=c)
1172- t.start()
1173- t.join()
1174- yappi.stop()
1175- yappi.start()
1176-
1177- def f():
1178- pass
1179-
1180- f()
1181- stats = yappi.get_func_stats()
1182- fsa = utils.find_stat_by_name(stats, 'a')
1183- fsb = utils.find_stat_by_name(stats, 'b')
1184- fsc = utils.find_stat_by_name(stats, 'c')
1185- self.assertEqual(fsa.ncall, 10)
1186- self.assertEqual(fsb.ncall, 5)
1187- self.assertEqual(fsc.ncall, 5)
1188- self.assertEqual(fsa.ttot, fsa.tsub, 30)
1189- self.assertEqual(fsb.ttot, fsb.tsub, 10)
1190- self.assertEqual(fsc.ttot, fsc.tsub, 5)
1191-
1192- # MACOSx optimizes by only creating one worker thread
1193- self.assertTrue(len(yappi.get_thread_stats()) >= 2)
1194-
1195- def test_basic(self):
1196- yappi.set_clock_type('wall')
1197-
1198- def dummy():
1199- pass
1200-
1201- def a():
1202- time.sleep(0.2)
1203-
1204- class Worker1(threading.Thread):
1205-
1206- def a(self):
1207- time.sleep(0.3)
1208-
1209- def run(self):
1210- self.a()
1211-
1212- yappi.start(builtins=False, profile_threads=True)
1213-
1214- c = Worker1()
1215- c.start()
1216- c.join()
1217- a()
1218- stats = yappi.get_func_stats()
1219- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
1220- fsa2 = utils.find_stat_by_name(stats, 'a')
1221- self.assertTrue(fsa1 is not None)
1222- self.assertTrue(fsa2 is not None)
1223- self.assertTrue(fsa1.ttot > 0.2)
1224- self.assertTrue(fsa2.ttot > 0.1)
1225- tstats = yappi.get_thread_stats()
1226- self.assertEqual(len(tstats), 2)
1227- tsa = utils.find_stat_by_name(tstats, 'Worker1')
1228- tsm = utils.find_stat_by_name(tstats, '_MainThread')
1229- dummy() # call dummy to force ctx name to be retrieved again.
1230- self.assertTrue(tsa is not None)
1231- # TODO: I put dummy() to fix below, remove the comments after a while.
1232- self.assertTrue( # FIX: I see this fails sometimes?
1233- tsm is not None,
1234- 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
1235-
1236- def test_ctx_stats(self):
1237- from threading import Thread
1238- DUMMY_WORKER_COUNT = 5
1239- yappi.start()
1240-
1241- class DummyThread(Thread):
1242- pass
1243-
1244- def dummy():
1245- pass
1246-
1247- def dummy_worker():
1248- pass
1249-
1250- for i in range(DUMMY_WORKER_COUNT):
1251- t = DummyThread(target=dummy_worker)
1252- t.start()
1253- t.join()
1254- yappi.stop()
1255- stats = yappi.get_thread_stats()
1256- tsa = utils.find_stat_by_name(stats, "DummyThread")
1257- self.assertTrue(tsa is not None)
1258- yappi.clear_stats()
1259- time.sleep(1.0)
1260- _timings = {
1261- "a_1": 6,
1262- "b_1": 5,
1263- "c_1": 3,
1264- "d_1": 1,
1265- "a_2": 4,
1266- "b_2": 3,
1267- "c_2": 2,
1268- "d_2": 1
1269- }
1270- _yappi._set_test_timings(_timings)
1271-
1272- class Thread1(Thread):
1273- pass
1274-
1275- class Thread2(Thread):
1276- pass
1277-
1278- def a():
1279- b()
1280-
1281- def b():
1282- c()
1283-
1284- def c():
1285- d()
1286-
1287- def d():
1288- time.sleep(0.6)
1289-
1290- yappi.set_clock_type("wall")
1291- yappi.start()
1292- t1 = Thread1(target=a)
1293- t1.start()
1294- t2 = Thread2(target=a)
1295- t2.start()
1296- t1.join()
1297- t2.join()
1298- stats = yappi.get_thread_stats()
1299-
1300- # the fist clear_stats clears the context table?
1301- tsa = utils.find_stat_by_name(stats, "DummyThread")
1302- self.assertTrue(tsa is None)
1303-
1304- tst1 = utils.find_stat_by_name(stats, "Thread1")
1305- tst2 = utils.find_stat_by_name(stats, "Thread2")
1306- tsmain = utils.find_stat_by_name(stats, "_MainThread")
1307- dummy() # call dummy to force ctx name to be retrieved again.
1308- self.assertTrue(len(stats) == 3)
1309- self.assertTrue(tst1 is not None)
1310- self.assertTrue(tst2 is not None)
1311- # TODO: I put dummy() to fix below, remove the comments after a while.
1312- self.assertTrue( # FIX: I see this fails sometimes
1313- tsmain is not None,
1314- 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
1315- self.assertTrue(1.0 > tst2.ttot >= 0.5)
1316- self.assertTrue(1.0 > tst1.ttot >= 0.5)
1317-
1318- # test sorting of the ctx stats
1319- stats = stats.sort("totaltime", "desc")
1320- prev_stat = None
1321- for stat in stats:
1322- if prev_stat:
1323- self.assertTrue(prev_stat.ttot >= stat.ttot)
1324- prev_stat = stat
1325- stats = stats.sort("totaltime", "asc")
1326- prev_stat = None
1327- for stat in stats:
1328- if prev_stat:
1329- self.assertTrue(prev_stat.ttot <= stat.ttot)
1330- prev_stat = stat
1331- stats = stats.sort("schedcount", "desc")
1332- prev_stat = None
1333- for stat in stats:
1334- if prev_stat:
1335- self.assertTrue(prev_stat.sched_count >= stat.sched_count)
1336- prev_stat = stat
1337- stats = stats.sort("name", "desc")
1338- prev_stat = None
1339- for stat in stats:
1340- if prev_stat:
1341- self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
1342- prev_stat = stat
1343- self.assertRaises(
1344- yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
1345- )
1346- self.assertRaises(
1347- yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
1348- )
1349-
1350- def test_ctx_stats_cpu(self):
1351-
1352- def get_thread_name():
1353- try:
1354- return threading.current_thread().name
1355- except AttributeError:
1356- return "Anonymous"
1357-
1358- def burn_cpu(sec):
1359- t0 = yappi.get_clock_time()
1360- elapsed = 0
1361- while (elapsed < sec):
1362- for _ in range(1000):
1363- pass
1364- elapsed = yappi.get_clock_time() - t0
1365-
1366- def test():
1367-
1368- ts = []
1369- for i in (0.01, 0.05, 0.1):
1370- t = threading.Thread(target=burn_cpu, args=(i, ))
1371- t.name = "burn_cpu-%s" % str(i)
1372- t.start()
1373- ts.append(t)
1374- for t in ts:
1375- t.join()
1376-
1377- yappi.set_clock_type("cpu")
1378- yappi.set_context_name_callback(get_thread_name)
1379-
1380- yappi.start()
1381-
1382- test()
1383-
1384- yappi.stop()
1385-
1386- tstats = yappi.get_thread_stats()
1387- r1 = '''
1388- burn_cpu-0.1 3 123145356058624 0.100105 8
1389- burn_cpu-0.05 2 123145361313792 0.050149 8
1390- burn_cpu-0.01 1 123145356058624 0.010127 2
1391- MainThread 0 4321620864 0.001632 6
1392- '''
1393- self.assert_ctx_stats_almost_equal(r1, tstats)
1394-
1395- def test_producer_consumer_with_queues(self):
1396- # we currently just stress yappi, no functionality test is done here.
1397- yappi.start()
1398- if utils.is_py3x():
1399- from queue import Queue
1400- else:
1401- from Queue import Queue
1402- from threading import Thread
1403- WORKER_THREAD_COUNT = 50
1404- WORK_ITEM_COUNT = 2000
1405-
1406- def worker():
1407- while True:
1408- item = q.get()
1409- # do the work with item
1410- q.task_done()
1411-
1412- q = Queue()
1413- for i in range(WORKER_THREAD_COUNT):
1414- t = Thread(target=worker)
1415- t.daemon = True
1416- t.start()
1417-
1418- for item in range(WORK_ITEM_COUNT):
1419- q.put(item)
1420- q.join() # block until all tasks are done
1421- #yappi.get_func_stats().sort("callcount").print_all()
1422- yappi.stop()
1423-
1424- def test_temporary_lock_waiting(self):
1425- yappi.start()
1426- _lock = threading.Lock()
1427-
1428- def worker():
1429- _lock.acquire()
1430- try:
1431- time.sleep(1.0)
1432- finally:
1433- _lock.release()
1434-
1435- t1 = threading.Thread(target=worker)
1436- t2 = threading.Thread(target=worker)
1437- t1.start()
1438- t2.start()
1439- t1.join()
1440- t2.join()
1441- #yappi.get_func_stats().sort("callcount").print_all()
1442- yappi.stop()
1443-
1444- @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
1445- def test_signals_with_blocking_calls(self):
1446- import signal, os, time
1447-
1448- # just to verify if signal is handled correctly and stats/yappi are not corrupted.
1449- def handler(signum, frame):
1450- raise Exception("Signal handler executed!")
1451-
1452- yappi.start()
1453- signal.signal(signal.SIGALRM, handler)
1454- signal.alarm(1)
1455- self.assertRaises(Exception, time.sleep, 2)
1456- stats = yappi.get_func_stats()
1457- fsh = utils.find_stat_by_name(stats, "handler")
1458- self.assertTrue(fsh is not None)
1459-
1460- @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
1461- def test_concurrent_futures(self):
1462- yappi.start()
1463- from concurrent.futures import ThreadPoolExecutor
1464- with ThreadPoolExecutor(max_workers=5) as executor:
1465- f = executor.submit(pow, 5, 2)
1466- self.assertEqual(f.result(), 25)
1467- time.sleep(1.0)
1468- yappi.stop()
1469-
1470- @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
1471- def test_barrier(self):
1472- yappi.start()
1473- b = threading.Barrier(2, timeout=1)
1474-
1475- def worker():
1476- try:
1477- b.wait()
1478- except threading.BrokenBarrierError:
1479- pass
1480- except Exception:
1481- raise Exception("BrokenBarrierError not raised")
1482-
1483- t1 = threading.Thread(target=worker)
1484- t1.start()
1485- #b.wait()
1486- t1.join()
1487- yappi.stop()
1488-
1489-
1490-class NonRecursiveFunctions(utils.YappiUnitTestCase):
1491-
1492- def test_abcd(self):
1493- _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
1494- _yappi._set_test_timings(_timings)
1495-
1496- def a():
1497- b()
1498-
1499- def b():
1500- c()
1501-
1502- def c():
1503- d()
1504-
1505- def d():
1506- pass
1507-
1508- stats = utils.run_and_get_func_stats(a)
1509- fsa = utils.find_stat_by_name(stats, 'a')
1510- fsb = utils.find_stat_by_name(stats, 'b')
1511- fsc = utils.find_stat_by_name(stats, 'c')
1512- fsd = utils.find_stat_by_name(stats, 'd')
1513- cfsab = fsa.children[fsb]
1514- cfsbc = fsb.children[fsc]
1515- cfscd = fsc.children[fsd]
1516-
1517- self.assertEqual(fsa.ttot, 6)
1518- self.assertEqual(fsa.tsub, 1)
1519- self.assertEqual(fsb.ttot, 5)
1520- self.assertEqual(fsb.tsub, 2)
1521- self.assertEqual(fsc.ttot, 3)
1522- self.assertEqual(fsc.tsub, 2)
1523- self.assertEqual(fsd.ttot, 1)
1524- self.assertEqual(fsd.tsub, 1)
1525- self.assertEqual(cfsab.ttot, 5)
1526- self.assertEqual(cfsab.tsub, 2)
1527- self.assertEqual(cfsbc.ttot, 3)
1528- self.assertEqual(cfsbc.tsub, 2)
1529- self.assertEqual(cfscd.ttot, 1)
1530- self.assertEqual(cfscd.tsub, 1)
1531-
1532- def test_stop_in_middle(self):
1533- _timings = {"a_1": 6, "b_1": 4}
1534- _yappi._set_test_timings(_timings)
1535-
1536- def a():
1537- b()
1538- yappi.stop()
1539-
1540- def b():
1541- time.sleep(0.2)
1542-
1543- yappi.start()
1544- a()
1545- stats = yappi.get_func_stats()
1546- fsa = utils.find_stat_by_name(stats, 'a')
1547- fsb = utils.find_stat_by_name(stats, 'b')
1548-
1549- self.assertEqual(fsa.ncall, 1)
1550- self.assertEqual(fsa.nactualcall, 0)
1551- self.assertEqual(fsa.ttot, 0) # no call_leave called
1552- self.assertEqual(fsa.tsub, 0) # no call_leave called
1553- self.assertEqual(fsb.ttot, 4)
1554-
1555-
1556-class RecursiveFunctions(utils.YappiUnitTestCase):
1557-
1558- def test_fibonacci(self):
1559-
1560- def fib(n):
1561- if n > 1:
1562- return fib(n - 1) + fib(n - 2)
1563- else:
1564- return n
1565-
1566- stats = utils.run_and_get_func_stats(fib, 22)
1567- fs = utils.find_stat_by_name(stats, 'fib')
1568- self.assertEqual(fs.ncall, 57313)
1569- self.assertEqual(fs.ttot, fs.tsub)
1570-
1571- def test_abcadc(self):
1572- _timings = {
1573- "a_1": 20,
1574- "b_1": 19,
1575- "c_1": 17,
1576- "a_2": 13,
1577- "d_1": 12,
1578- "c_2": 10,
1579- "a_3": 5
1580- }
1581- _yappi._set_test_timings(_timings)
1582-
1583- def a(n):
1584- if n == 3:
1585- return
1586- if n == 1 + 1:
1587- d(n)
1588- else:
1589- b(n)
1590-
1591- def b(n):
1592- c(n)
1593-
1594- def c(n):
1595- a(n + 1)
1596-
1597- def d(n):
1598- c(n)
1599-
1600- stats = utils.run_and_get_func_stats(a, 1)
1601- fsa = utils.find_stat_by_name(stats, 'a')
1602- fsb = utils.find_stat_by_name(stats, 'b')
1603- fsc = utils.find_stat_by_name(stats, 'c')
1604- fsd = utils.find_stat_by_name(stats, 'd')
1605- self.assertEqual(fsa.ncall, 3)
1606- self.assertEqual(fsa.nactualcall, 1)
1607- self.assertEqual(fsa.ttot, 20)
1608- self.assertEqual(fsa.tsub, 7)
1609- self.assertEqual(fsb.ttot, 19)
1610- self.assertEqual(fsb.tsub, 2)
1611- self.assertEqual(fsc.ttot, 17)
1612- self.assertEqual(fsc.tsub, 9)
1613- self.assertEqual(fsd.ttot, 12)
1614- self.assertEqual(fsd.tsub, 2)
1615- cfsca = fsc.children[fsa]
1616- self.assertEqual(cfsca.nactualcall, 0)
1617- self.assertEqual(cfsca.ncall, 2)
1618- self.assertEqual(cfsca.ttot, 13)
1619- self.assertEqual(cfsca.tsub, 6)
1620-
1621- def test_aaaa(self):
1622- _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
1623- _yappi._set_test_timings(_timings)
1624-
1625- def d(n):
1626- if n == 3:
1627- return
1628- d(n + 1)
1629-
1630- stats = utils.run_and_get_func_stats(d, 0)
1631- fsd = utils.find_stat_by_name(stats, 'd')
1632- self.assertEqual(fsd.ncall, 4)
1633- self.assertEqual(fsd.nactualcall, 1)
1634- self.assertEqual(fsd.ttot, 9)
1635- self.assertEqual(fsd.tsub, 9)
1636- cfsdd = fsd.children[fsd]
1637- self.assertEqual(cfsdd.ttot, 7)
1638- self.assertEqual(cfsdd.tsub, 7)
1639- self.assertEqual(cfsdd.ncall, 3)
1640- self.assertEqual(cfsdd.nactualcall, 0)
1641-
1642- def test_abcabc(self):
1643- _timings = {
1644- "a_1": 20,
1645- "b_1": 19,
1646- "c_1": 17,
1647- "a_2": 13,
1648- "b_2": 11,
1649- "c_2": 9,
1650- "a_3": 6
1651- }
1652- _yappi._set_test_timings(_timings)
1653-
1654- def a(n):
1655- if n == 3:
1656- return
1657- else:
1658- b(n)
1659-
1660- def b(n):
1661- c(n)
1662-
1663- def c(n):
1664- a(n + 1)
1665-
1666- stats = utils.run_and_get_func_stats(a, 1)
1667- fsa = utils.find_stat_by_name(stats, 'a')
1668- fsb = utils.find_stat_by_name(stats, 'b')
1669- fsc = utils.find_stat_by_name(stats, 'c')
1670- self.assertEqual(fsa.ncall, 3)
1671- self.assertEqual(fsa.nactualcall, 1)
1672- self.assertEqual(fsa.ttot, 20)
1673- self.assertEqual(fsa.tsub, 9)
1674- self.assertEqual(fsb.ttot, 19)
1675- self.assertEqual(fsb.tsub, 4)
1676- self.assertEqual(fsc.ttot, 17)
1677- self.assertEqual(fsc.tsub, 7)
1678- cfsab = fsa.children[fsb]
1679- cfsbc = fsb.children[fsc]
1680- cfsca = fsc.children[fsa]
1681- self.assertEqual(cfsab.ttot, 19)
1682- self.assertEqual(cfsab.tsub, 4)
1683- self.assertEqual(cfsbc.ttot, 17)
1684- self.assertEqual(cfsbc.tsub, 7)
1685- self.assertEqual(cfsca.ttot, 13)
1686- self.assertEqual(cfsca.tsub, 8)
1687-
1688- def test_abcbca(self):
1689- _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
1690- _yappi._set_test_timings(_timings)
1691- self._ncall = 1
1692-
1693- def a():
1694- if self._ncall == 1:
1695- b()
1696- else:
1697- return
1698-
1699- def b():
1700- c()
1701-
1702- def c():
1703- if self._ncall == 1:
1704- self._ncall += 1
1705- b()
1706- else:
1707- a()
1708-
1709- stats = utils.run_and_get_func_stats(a)
1710- fsa = utils.find_stat_by_name(stats, 'a')
1711- fsb = utils.find_stat_by_name(stats, 'b')
1712- fsc = utils.find_stat_by_name(stats, 'c')
1713- cfsab = fsa.children[fsb]
1714- cfsbc = fsb.children[fsc]
1715- cfsca = fsc.children[fsa]
1716- self.assertEqual(fsa.ttot, 10)
1717- self.assertEqual(fsa.tsub, 2)
1718- self.assertEqual(fsb.ttot, 9)
1719- self.assertEqual(fsb.tsub, 4)
1720- self.assertEqual(fsc.ttot, 7)
1721- self.assertEqual(fsc.tsub, 4)
1722- self.assertEqual(cfsab.ttot, 9)
1723- self.assertEqual(cfsab.tsub, 2)
1724- self.assertEqual(cfsbc.ttot, 7)
1725- self.assertEqual(cfsbc.tsub, 4)
1726- self.assertEqual(cfsca.ttot, 1)
1727- self.assertEqual(cfsca.tsub, 1)
1728- self.assertEqual(cfsca.ncall, 1)
1729- self.assertEqual(cfsca.nactualcall, 0)
1730-
1731- def test_aabccb(self):
1732- _timings = {
1733- "a_1": 13,
1734- "a_2": 11,
1735- "b_1": 9,
1736- "c_1": 5,
1737- "c_2": 3,
1738- "b_2": 1
1739- }
1740- _yappi._set_test_timings(_timings)
1741- self._ncall = 1
1742-
1743- def a():
1744- if self._ncall == 1:
1745- self._ncall += 1
1746- a()
1747- else:
1748- b()
1749-
1750- def b():
1751- if self._ncall == 3:
1752- return
1753- else:
1754- c()
1755-
1756- def c():
1757- if self._ncall == 2:
1758- self._ncall += 1
1759- c()
1760- else:
1761- b()
1762-
1763- stats = utils.run_and_get_func_stats(a)
1764- fsa = utils.find_stat_by_name(stats, 'a')
1765- fsb = utils.find_stat_by_name(stats, 'b')
1766- fsc = utils.find_stat_by_name(stats, 'c')
1767- cfsaa = fsa.children[fsa.index]
1768- cfsab = fsa.children[fsb]
1769- cfsbc = fsb.children[fsc.full_name]
1770- cfscc = fsc.children[fsc]
1771- cfscb = fsc.children[fsb]
1772- self.assertEqual(fsb.ttot, 9)
1773- self.assertEqual(fsb.tsub, 5)
1774- self.assertEqual(cfsbc.ttot, 5)
1775- self.assertEqual(cfsbc.tsub, 2)
1776- self.assertEqual(fsa.ttot, 13)
1777- self.assertEqual(fsa.tsub, 4)
1778- self.assertEqual(cfsab.ttot, 9)
1779- self.assertEqual(cfsab.tsub, 4)
1780- self.assertEqual(cfsaa.ttot, 11)
1781- self.assertEqual(cfsaa.tsub, 2)
1782- self.assertEqual(fsc.ttot, 5)
1783- self.assertEqual(fsc.tsub, 4)
1784-
1785- def test_abaa(self):
1786- _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
1787- _yappi._set_test_timings(_timings)
1788-
1789- self._ncall = 1
1790-
1791- def a():
1792- if self._ncall == 1:
1793- b()
1794- elif self._ncall == 2:
1795- self._ncall += 1
1796- a()
1797- else:
1798- return
1799-
1800- def b():
1801- self._ncall += 1
1802- a()
1803-
1804- stats = utils.run_and_get_func_stats(a)
1805- fsa = utils.find_stat_by_name(stats, 'a')
1806- fsb = utils.find_stat_by_name(stats, 'b')
1807- cfsaa = fsa.children[fsa]
1808- cfsba = fsb.children[fsa]
1809- self.assertEqual(fsb.ttot, 10)
1810- self.assertEqual(fsb.tsub, 1)
1811- self.assertEqual(fsa.ttot, 13)
1812- self.assertEqual(fsa.tsub, 12)
1813- self.assertEqual(cfsaa.ttot, 5)
1814- self.assertEqual(cfsaa.tsub, 5)
1815- self.assertEqual(cfsba.ttot, 9)
1816- self.assertEqual(cfsba.tsub, 4)
1817-
1818- def test_aabb(self):
1819- _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
1820- _yappi._set_test_timings(_timings)
1821-
1822- self._ncall = 1
1823-
1824- def a():
1825- if self._ncall == 1:
1826- self._ncall += 1
1827- a()
1828- elif self._ncall == 2:
1829- b()
1830- else:
1831- return
1832-
1833- def b():
1834- if self._ncall == 2:
1835- self._ncall += 1
1836- b()
1837- else:
1838- return
1839-
1840- stats = utils.run_and_get_func_stats(a)
1841- fsa = utils.find_stat_by_name(stats, 'a')
1842- fsb = utils.find_stat_by_name(stats, 'b')
1843- cfsaa = fsa.children[fsa]
1844- cfsab = fsa.children[fsb]
1845- cfsbb = fsb.children[fsb]
1846- self.assertEqual(fsa.ttot, 13)
1847- self.assertEqual(fsa.tsub, 4)
1848- self.assertEqual(fsb.ttot, 9)
1849- self.assertEqual(fsb.tsub, 9)
1850- self.assertEqual(cfsaa.ttot, 10)
1851- self.assertEqual(cfsaa.tsub, 1)
1852- self.assertEqual(cfsab.ttot, 9)
1853- self.assertEqual(cfsab.tsub, 4)
1854- self.assertEqual(cfsbb.ttot, 5)
1855- self.assertEqual(cfsbb.tsub, 5)
1856-
1857- def test_abbb(self):
1858- _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
1859- _yappi._set_test_timings(_timings)
1860-
1861- self._ncall = 1
1862-
1863- def a():
1864- if self._ncall == 1:
1865- b()
1866-
1867- def b():
1868- if self._ncall == 3:
1869- return
1870- self._ncall += 1
1871- b()
1872-
1873- stats = utils.run_and_get_func_stats(a)
1874- fsa = utils.find_stat_by_name(stats, 'a')
1875- fsb = utils.find_stat_by_name(stats, 'b')
1876- cfsab = fsa.children[fsb]
1877- cfsbb = fsb.children[fsb]
1878- self.assertEqual(fsa.ttot, 13)
1879- self.assertEqual(fsa.tsub, 3)
1880- self.assertEqual(fsb.ttot, 10)
1881- self.assertEqual(fsb.tsub, 10)
1882- self.assertEqual(fsb.ncall, 3)
1883- self.assertEqual(fsb.nactualcall, 1)
1884- self.assertEqual(cfsab.ttot, 10)
1885- self.assertEqual(cfsab.tsub, 4)
1886- self.assertEqual(cfsbb.ttot, 6)
1887- self.assertEqual(cfsbb.tsub, 6)
1888- self.assertEqual(cfsbb.nactualcall, 0)
1889- self.assertEqual(cfsbb.ncall, 2)
1890-
1891- def test_aaab(self):
1892- _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
1893- _yappi._set_test_timings(_timings)
1894-
1895- self._ncall = 1
1896-
1897- def a():
1898- if self._ncall == 3:
1899- b()
1900- return
1901- self._ncall += 1
1902- a()
1903-
1904- def b():
1905- return
1906-
1907- stats = utils.run_and_get_func_stats(a)
1908- fsa = utils.find_stat_by_name(stats, 'a')
1909- fsb = utils.find_stat_by_name(stats, 'b')
1910- cfsaa = fsa.children[fsa]
1911- cfsab = fsa.children[fsb]
1912- self.assertEqual(fsa.ttot, 13)
1913- self.assertEqual(fsa.tsub, 12)
1914- self.assertEqual(fsb.ttot, 1)
1915- self.assertEqual(fsb.tsub, 1)
1916- self.assertEqual(cfsaa.ttot, 10)
1917- self.assertEqual(cfsaa.tsub, 9)
1918- self.assertEqual(cfsab.ttot, 1)
1919- self.assertEqual(cfsab.tsub, 1)
1920-
1921- def test_abab(self):
1922- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
1923- _yappi._set_test_timings(_timings)
1924-
1925- self._ncall = 1
1926-
1927- def a():
1928- b()
1929-
1930- def b():
1931- if self._ncall == 2:
1932- return
1933- self._ncall += 1
1934- a()
1935-
1936- stats = utils.run_and_get_func_stats(a)
1937- fsa = utils.find_stat_by_name(stats, 'a')
1938- fsb = utils.find_stat_by_name(stats, 'b')
1939- cfsab = fsa.children[fsb]
1940- cfsba = fsb.children[fsa]
1941- self.assertEqual(fsa.ttot, 13)
1942- self.assertEqual(fsa.tsub, 8)
1943- self.assertEqual(fsb.ttot, 10)
1944- self.assertEqual(fsb.tsub, 5)
1945- self.assertEqual(cfsab.ttot, 10)
1946- self.assertEqual(cfsab.tsub, 5)
1947- self.assertEqual(cfsab.ncall, 2)
1948- self.assertEqual(cfsab.nactualcall, 1)
1949- self.assertEqual(cfsba.ttot, 6)
1950- self.assertEqual(cfsba.tsub, 5)
1951-
1952-
1953-if __name__ == '__main__':
1954- # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
1955- # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
1956- unittest.main()
1957+import os
1958+import sys
1959+import time
1960+import threading
1961+import unittest
1962+import yappi
1963+import _yappi
1964+import tests.utils as utils
1965+import multiprocessing # added to fix http://bugs.python.org/issue15881 for > Py2.6
1966+import subprocess
1967+
1968+_counter = 0
1969+
1970+
1971+class BasicUsage(utils.YappiUnitTestCase):
1972+
1973+ def test_callback_function_int_return_overflow(self):
1974+ # this test is just here to check if any errors are generated, as the err
1975+ # is printed in C side, I did not include it here. THere are ways to test
1976+ # this deterministically, I did not bother
1977+ import ctypes
1978+
1979+ def _unsigned_overflow_margin():
1980+ return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
1981+
1982+ def foo():
1983+ pass
1984+
1985+ #with utils.captured_output() as (out, err):
1986+ yappi.set_context_id_callback(_unsigned_overflow_margin)
1987+ yappi.set_tag_callback(_unsigned_overflow_margin)
1988+ yappi.start()
1989+ foo()
1990+
1991+ def test_issue60(self):
1992+
1993+ def foo():
1994+ buf = bytearray()
1995+ buf += b't' * 200
1996+ view = memoryview(buf)[10:]
1997+ view = view.tobytes()
1998+ del buf[:10] # this throws exception
1999+ return view
2000+
2001+ yappi.start(builtins=True)
2002+ foo()
2003+ self.assertTrue(
2004+ len(
2005+ yappi.get_func_stats(
2006+ filter_callback=lambda x: yappi.
2007+ func_matches(x, [memoryview.tobytes])
2008+ )
2009+ ) > 0
2010+ )
2011+ yappi.stop()
2012+
2013+ def test_issue54(self):
2014+
2015+ def _tag_cbk():
2016+ global _counter
2017+ _counter += 1
2018+ return _counter
2019+
2020+ def a():
2021+ pass
2022+
2023+ def b():
2024+ pass
2025+
2026+ yappi.set_tag_callback(_tag_cbk)
2027+ yappi.start()
2028+ a()
2029+ a()
2030+ a()
2031+ yappi.stop()
2032+ stats = yappi.get_func_stats()
2033+ self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given
2034+ stats = yappi.get_func_stats(tag=1)
2035+
2036+ for i in range(1, 3):
2037+ stats = yappi.get_func_stats(tag=i)
2038+ stats = yappi.get_func_stats(
2039+ tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
2040+ )
2041+
2042+ stat = stats.pop()
2043+ self.assertEqual(stat.ncall, 1)
2044+
2045+ yappi.set_tag_callback(None)
2046+ yappi.clear_stats()
2047+ yappi.start()
2048+ b()
2049+ b()
2050+ stats = yappi.get_func_stats()
2051+ self.assertEqual(len(stats), 1)
2052+ stat = stats.pop()
2053+ self.assertEqual(stat.ncall, 2)
2054+
2055+ def test_filter(self):
2056+
2057+ def a():
2058+ pass
2059+
2060+ def b():
2061+ a()
2062+
2063+ def c():
2064+ b()
2065+
2066+ _TCOUNT = 5
2067+
2068+ ts = []
2069+ yappi.start()
2070+ for i in range(_TCOUNT):
2071+ t = threading.Thread(target=c)
2072+ t.start()
2073+ ts.append(t)
2074+
2075+ for t in ts:
2076+ t.join()
2077+
2078+ yappi.stop()
2079+
2080+ ctx_ids = []
2081+ for tstat in yappi.get_thread_stats():
2082+ if tstat.name == '_MainThread':
2083+ main_ctx_id = tstat.id
2084+ else:
2085+ ctx_ids.append(tstat.id)
2086+
2087+ fstats = yappi.get_func_stats(filter={"ctx_id": 9})
2088+ self.assertTrue(fstats.empty())
2089+ fstats = yappi.get_func_stats(
2090+ filter={
2091+ "ctx_id": main_ctx_id,
2092+ "name": "c"
2093+ }
2094+ ) # main thread
2095+ self.assertTrue(fstats.empty())
2096+
2097+ for i in ctx_ids:
2098+ fstats = yappi.get_func_stats(
2099+ filter={
2100+ "ctx_id": i,
2101+ "name": "a",
2102+ "ncall": 1
2103+ }
2104+ )
2105+ self.assertEqual(fstats.pop().ncall, 1)
2106+ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
2107+ self.assertEqual(fstats.pop().ncall, 1)
2108+ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
2109+ self.assertEqual(fstats.pop().ncall, 1)
2110+
2111+ yappi.clear_stats()
2112+ yappi.start(builtins=True)
2113+ time.sleep(0.1)
2114+ yappi.stop()
2115+ fstats = yappi.get_func_stats(filter={"module": "time"})
2116+ self.assertEqual(len(fstats), 1)
2117+
2118+ # invalid filters`
2119+ self.assertRaises(
2120+ Exception, yappi.get_func_stats, filter={'tag': "sss"}
2121+ )
2122+ self.assertRaises(
2123+ Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
2124+ )
2125+
2126+ def test_filter_callback(self):
2127+
2128+ def a():
2129+ time.sleep(0.1)
2130+
2131+ def b():
2132+ a()
2133+
2134+ def c():
2135+ pass
2136+
2137+ def d():
2138+ pass
2139+
2140+ yappi.set_clock_type("wall")
2141+ yappi.start(builtins=True)
2142+ a()
2143+ b()
2144+ c()
2145+ d()
2146+ stats = yappi.get_func_stats(
2147+ filter_callback=lambda x: yappi.func_matches(x, [a, b])
2148+ )
2149+ #stats.print_all()
2150+ r1 = '''
2151+ tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175
2152+ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197
2153+ '''
2154+ self.assert_traces_almost_equal(r1, stats)
2155+ self.assertEqual(len(stats), 2)
2156+ stats = yappi.get_func_stats(
2157+ filter_callback=lambda x: yappi.
2158+ module_matches(x, [sys.modules[__name__]])
2159+ )
2160+ r1 = '''
2161+ tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065
2162+ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011
2163+ tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002
2164+ tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001
2165+ '''
2166+ self.assert_traces_almost_equal(r1, stats)
2167+ self.assertEqual(len(stats), 4)
2168+
2169+ stats = yappi.get_func_stats(
2170+ filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
2171+ )
2172+ self.assertEqual(len(stats), 1)
2173+ r1 = '''
2174+ time.sleep 2 0.206804 0.220000 0.103402
2175+ '''
2176+ self.assert_traces_almost_equal(r1, stats)
2177+
2178+ def test_print_formatting(self):
2179+
2180+ def a():
2181+ pass
2182+
2183+ def b():
2184+ a()
2185+
2186+ func_cols = {
2187+ 1: ("name", 48),
2188+ 0: ("ncall", 5),
2189+ 2: ("tsub", 8),
2190+ }
2191+ thread_cols = {
2192+ 1: ("name", 48),
2193+ 0: ("ttot", 8),
2194+ }
2195+
2196+ yappi.start()
2197+ a()
2198+ b()
2199+ yappi.stop()
2200+ fs = yappi.get_func_stats()
2201+ cs = fs[1].children
2202+ ts = yappi.get_thread_stats()
2203+ #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
2204+ #cs.print_all(out=sys.stderr, columns=func_cols)
2205+ #ts.print_all(out=sys.stderr, columns=thread_cols)
2206+ #cs.print_all(out=sys.stderr, columns={})
2207+
2208+ self.assertRaises(
2209+ yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
2210+ )
2211+ self.assertRaises(
2212+ yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
2213+ )
2214+ self.assertRaises(
2215+ yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
2216+ )
2217+
2218+ def test_get_clock(self):
2219+ yappi.set_clock_type('cpu')
2220+ self.assertEqual('cpu', yappi.get_clock_type())
2221+ clock_info = yappi.get_clock_info()
2222+ self.assertTrue('api' in clock_info)
2223+ self.assertTrue('resolution' in clock_info)
2224+
2225+ yappi.set_clock_type('wall')
2226+ self.assertEqual('wall', yappi.get_clock_type())
2227+
2228+ t0 = yappi.get_clock_time()
2229+ time.sleep(0.1)
2230+ duration = yappi.get_clock_time() - t0
2231+ self.assertTrue(0.05 < duration < 0.3)
2232+
2233+ def test_profile_decorator(self):
2234+
2235+ def aggregate(func, stats):
2236+ fname = "tests/%s.profile" % (func.__name__)
2237+ try:
2238+ stats.add(fname)
2239+ except IOError:
2240+ pass
2241+ stats.save(fname)
2242+ raise Exception("messing around")
2243+
2244+ @yappi.profile(return_callback=aggregate)
2245+ def a(x, y):
2246+ if x + y == 25:
2247+ raise Exception("")
2248+ return x + y
2249+
2250+ def b():
2251+ pass
2252+
2253+ try:
2254+ os.remove(
2255+ "tests/a.profile"
2256+ ) # remove the one from prev test, if available
2257+ except:
2258+ pass
2259+
2260+ # global profile is on to mess things up
2261+ yappi.start()
2262+ b()
2263+
2264+ # assert functionality and call function at same time
2265+ try:
2266+ self.assertEqual(a(1, 2), 3)
2267+ except:
2268+ pass
2269+ try:
2270+ self.assertEqual(a(2, 5), 7)
2271+ except:
2272+ pass
2273+ try:
2274+ a(4, 21)
2275+ except:
2276+ pass
2277+ stats = yappi.get_func_stats().add("tests/a.profile")
2278+ fsa = utils.find_stat_by_name(stats, 'a')
2279+ self.assertEqual(fsa.ncall, 3)
2280+ self.assertEqual(len(stats), 1) # b() should be cleared out.
2281+
2282+ @yappi.profile(return_callback=aggregate)
2283+ def count_down_rec(n):
2284+ if n == 0:
2285+ return
2286+ count_down_rec(n - 1)
2287+
2288+ try:
2289+ os.remove(
2290+ "tests/count_down_rec.profile"
2291+ ) # remove the one from prev test, if available
2292+ except:
2293+ pass
2294+
2295+ try:
2296+ count_down_rec(4)
2297+ except:
2298+ pass
2299+ try:
2300+ count_down_rec(3)
2301+ except:
2302+ pass
2303+
2304+ stats = yappi.YFuncStats("tests/count_down_rec.profile")
2305+ fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
2306+ self.assertEqual(fsrec.ncall, 9)
2307+ self.assertEqual(fsrec.nactualcall, 2)
2308+
2309+ def test_strip_dirs(self):
2310+
2311+ def a():
2312+ pass
2313+
2314+ stats = utils.run_and_get_func_stats(a, )
2315+ stats.strip_dirs()
2316+ fsa = utils.find_stat_by_name(stats, "a")
2317+ self.assertEqual(fsa.module, os.path.basename(fsa.module))
2318+
2319+ @unittest.skipIf(os.name == "nt", "do not run on Windows")
2320+ def test_run_as_script(self):
2321+ import re
2322+ p = subprocess.Popen(
2323+ ['yappi', os.path.join('./tests', 'run_as_script.py')],
2324+ stdout=subprocess.PIPE
2325+ )
2326+ out, err = p.communicate()
2327+ self.assertEqual(p.returncode, 0)
2328+ func_stats, thread_stats = re.split(
2329+ b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
2330+ )
2331+ self.assertTrue(b'FancyThread' in thread_stats)
2332+
2333+ def test_yappi_overhead(self):
2334+ LOOP_COUNT = 100000
2335+
2336+ def a():
2337+ pass
2338+
2339+ def b():
2340+ for i in range(LOOP_COUNT):
2341+ a()
2342+
2343+ t0 = time.time()
2344+ yappi.start()
2345+ b()
2346+ yappi.stop()
2347+ time_with_yappi = time.time() - t0
2348+ t0 = time.time()
2349+ b()
2350+ time_without_yappi = time.time() - t0
2351+ if time_without_yappi == 0:
2352+ time_without_yappi = 0.000001
2353+
2354+ # in latest v0.82, I calculated this as close to "7.0" in my machine.
2355+ # however, %83 of this overhead is coming from tickcount(). The other %17
2356+ # seems to have been evenly distributed to the internal bookkeeping
2357+ # structures/algorithms which seems acceptable. Note that our test only
2358+ # tests one function being profiled at-a-time in a short interval.
2359+ # profiling high number of functions in a small time
2360+ # is a different beast, (which is pretty unlikely in most applications)
2361+ # So as a conclusion: I cannot see any optimization window for Yappi that
2362+ # is worth implementing as we will only optimize %17 of the time.
2363+ sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
2364+ (time_with_yappi / time_without_yappi))
2365+
2366+ def test_clear_stats_while_running(self):
2367+
2368+ def a():
2369+ pass
2370+
2371+ yappi.start()
2372+ a()
2373+ yappi.clear_stats()
2374+ a()
2375+ stats = yappi.get_func_stats()
2376+ fsa = utils.find_stat_by_name(stats, 'a')
2377+ self.assertEqual(fsa.ncall, 1)
2378+
2379+ def test_generator(self):
2380+
2381+ def _gen(n):
2382+ while (n > 0):
2383+ yield n
2384+ n -= 1
2385+
2386+ yappi.start()
2387+ for x in _gen(5):
2388+ pass
2389+ self.assertTrue(
2390+ yappi.convert2pstats(yappi.get_func_stats()) is not None
2391+ )
2392+
2393+ def test_slice_child_stats_and_strip_dirs(self):
2394+
2395+ def b():
2396+ for i in range(10000000):
2397+ pass
2398+
2399+ def a():
2400+ b()
2401+
2402+ yappi.start(builtins=True)
2403+ a()
2404+ stats = yappi.get_func_stats()
2405+ fsa = utils.find_stat_by_name(stats, 'a')
2406+ fsb = utils.find_stat_by_name(stats, 'b')
2407+ self.assertTrue(fsa.children[0:1] is not None)
2408+ prev_afullname = fsa.full_name
2409+ prev_bchildfullname = fsa.children[fsb].full_name
2410+ stats.strip_dirs()
2411+ self.assertTrue(len(prev_afullname) > len(fsa.full_name))
2412+ self.assertTrue(
2413+ len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
2414+ )
2415+
2416+ def test_children_stat_functions(self):
2417+ _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
2418+ _yappi._set_test_timings(_timings)
2419+
2420+ def b():
2421+ pass
2422+
2423+ def c():
2424+ pass
2425+
2426+ def a():
2427+ b()
2428+ c()
2429+
2430+ yappi.start()
2431+ a()
2432+ b() # non-child call
2433+ c() # non-child call
2434+ stats = yappi.get_func_stats()
2435+ fsa = utils.find_stat_by_name(stats, 'a')
2436+ childs_of_a = fsa.children.get().sort("tavg", "desc")
2437+ prev_item = None
2438+ for item in childs_of_a:
2439+ if prev_item:
2440+ self.assertTrue(prev_item.tavg > item.tavg)
2441+ prev_item = item
2442+ childs_of_a.sort("name", "desc")
2443+ prev_item = None
2444+ for item in childs_of_a:
2445+ if prev_item:
2446+ self.assertTrue(prev_item.name > item.name)
2447+ prev_item = item
2448+ childs_of_a.clear()
2449+ self.assertTrue(childs_of_a.empty())
2450+
2451+ def test_no_stats_different_clock_type_load(self):
2452+
2453+ def a():
2454+ pass
2455+
2456+ yappi.start()
2457+ a()
2458+ yappi.stop()
2459+ yappi.get_func_stats().save("tests/ystats1.ys")
2460+ yappi.clear_stats()
2461+ yappi.set_clock_type("WALL")
2462+ yappi.start()
2463+ yappi.stop()
2464+ stats = yappi.get_func_stats().add("tests/ystats1.ys")
2465+ fsa = utils.find_stat_by_name(stats, 'a')
2466+ self.assertTrue(fsa is not None)
2467+
2468+ def test_subsequent_profile(self):
2469+ _timings = {"a_1": 1, "b_1": 1}
2470+ _yappi._set_test_timings(_timings)
2471+
2472+ def a():
2473+ pass
2474+
2475+ def b():
2476+ pass
2477+
2478+ yappi.start()
2479+ a()
2480+ yappi.stop()
2481+ yappi.start()
2482+ b()
2483+ yappi.stop()
2484+ stats = yappi.get_func_stats()
2485+ fsa = utils.find_stat_by_name(stats, 'a')
2486+ fsb = utils.find_stat_by_name(stats, 'b')
2487+ self.assertTrue(fsa is not None)
2488+ self.assertTrue(fsb is not None)
2489+ self.assertEqual(fsa.ttot, 1)
2490+ self.assertEqual(fsb.ttot, 1)
2491+
2492+ def test_lambda(self):
2493+ f = lambda: time.sleep(0.3)
2494+ yappi.set_clock_type("wall")
2495+ yappi.start()
2496+ f()
2497+ stats = yappi.get_func_stats()
2498+ fsa = utils.find_stat_by_name(stats, '<lambda>')
2499+ self.assertTrue(fsa.ttot > 0.1)
2500+
2501+ def test_module_stress(self):
2502+ self.assertEqual(yappi.is_running(), False)
2503+
2504+ yappi.start()
2505+ yappi.clear_stats()
2506+ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
2507+
2508+ yappi.stop()
2509+ yappi.clear_stats()
2510+ yappi.set_clock_type("cpu")
2511+ self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
2512+ self.assertEqual(yappi.is_running(), False)
2513+ yappi.clear_stats()
2514+ yappi.clear_stats()
2515+
2516+ def test_stat_sorting(self):
2517+ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
2518+ _yappi._set_test_timings(_timings)
2519+
2520+ self._ncall = 1
2521+
2522+ def a():
2523+ b()
2524+
2525+ def b():
2526+ if self._ncall == 2:
2527+ return
2528+ self._ncall += 1
2529+ a()
2530+
2531+ stats = utils.run_and_get_func_stats(a)
2532+ stats = stats.sort("totaltime", "desc")
2533+ prev_stat = None
2534+ for stat in stats:
2535+ if prev_stat:
2536+ self.assertTrue(prev_stat.ttot >= stat.ttot)
2537+ prev_stat = stat
2538+ stats = stats.sort("totaltime", "asc")
2539+ prev_stat = None
2540+ for stat in stats:
2541+ if prev_stat:
2542+ self.assertTrue(prev_stat.ttot <= stat.ttot)
2543+ prev_stat = stat
2544+ stats = stats.sort("avgtime", "asc")
2545+ prev_stat = None
2546+ for stat in stats:
2547+ if prev_stat:
2548+ self.assertTrue(prev_stat.tavg <= stat.tavg)
2549+ prev_stat = stat
2550+ stats = stats.sort("name", "asc")
2551+ prev_stat = None
2552+ for stat in stats:
2553+ if prev_stat:
2554+ self.assertTrue(prev_stat.name <= stat.name)
2555+ prev_stat = stat
2556+ stats = stats.sort("subtime", "asc")
2557+ prev_stat = None
2558+ for stat in stats:
2559+ if prev_stat:
2560+ self.assertTrue(prev_stat.tsub <= stat.tsub)
2561+ prev_stat = stat
2562+
2563+ self.assertRaises(
2564+ yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
2565+ )
2566+ self.assertRaises(
2567+ yappi.YappiError, stats.sort, "totaltime",
2568+ "invalid_func_sortorder_arg"
2569+ )
2570+
2571+ def test_start_flags(self):
2572+ self.assertEqual(_yappi._get_start_flags(), None)
2573+ yappi.start()
2574+
2575+ def a():
2576+ pass
2577+
2578+ a()
2579+ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
2580+ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
2581+ self.assertEqual(len(yappi.get_thread_stats()), 1)
2582+
2583+ def test_builtin_profiling(self):
2584+
2585+ def a():
2586+ time.sleep(0.4) # is a builtin function
2587+
2588+ yappi.set_clock_type('wall')
2589+
2590+ yappi.start(builtins=True)
2591+ a()
2592+ stats = yappi.get_func_stats()
2593+ fsa = utils.find_stat_by_name(stats, 'sleep')
2594+ self.assertTrue(fsa is not None)
2595+ self.assertTrue(fsa.ttot > 0.3)
2596+ yappi.stop()
2597+ yappi.clear_stats()
2598+
2599+ def a():
2600+ pass
2601+
2602+ yappi.start()
2603+ t = threading.Thread(target=a)
2604+ t.start()
2605+ t.join()
2606+ stats = yappi.get_func_stats()
2607+
2608+ def test_singlethread_profiling(self):
2609+ yappi.set_clock_type('wall')
2610+
2611+ def a():
2612+ time.sleep(0.2)
2613+
2614+ class Worker1(threading.Thread):
2615+
2616+ def a(self):
2617+ time.sleep(0.3)
2618+
2619+ def run(self):
2620+ self.a()
2621+
2622+ yappi.start(profile_threads=False)
2623+
2624+ c = Worker1()
2625+ c.start()
2626+ c.join()
2627+ a()
2628+ stats = yappi.get_func_stats()
2629+ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
2630+ fsa2 = utils.find_stat_by_name(stats, 'a')
2631+ self.assertTrue(fsa1 is None)
2632+ self.assertTrue(fsa2 is not None)
2633+ self.assertTrue(fsa2.ttot > 0.1)
2634+
2635+ def test_run(self):
2636+
2637+ def profiled():
2638+ pass
2639+
2640+ yappi.clear_stats()
2641+ try:
2642+ with yappi.run():
2643+ profiled()
2644+ stats = yappi.get_func_stats()
2645+ finally:
2646+ yappi.clear_stats()
2647+
2648+ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
2649+
2650+ def test_run_recursive(self):
2651+
2652+ def profiled():
2653+ pass
2654+
2655+ def not_profiled():
2656+ pass
2657+
2658+ yappi.clear_stats()
2659+ try:
2660+ with yappi.run():
2661+ with yappi.run():
2662+ profiled()
2663+ # Profiling stopped here
2664+ not_profiled()
2665+ stats = yappi.get_func_stats()
2666+ finally:
2667+ yappi.clear_stats()
2668+
2669+ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
2670+ self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
2671+
2672+
2673+class StatSaveScenarios(utils.YappiUnitTestCase):
2674+
2675+ def test_pstats_conversion(self):
2676+
2677+ def pstat_id(fs):
2678+ return (fs.module, fs.lineno, fs.name)
2679+
2680+ def a():
2681+ d()
2682+
2683+ def b():
2684+ d()
2685+
2686+ def c():
2687+ pass
2688+
2689+ def d():
2690+ pass
2691+
2692+ _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
2693+ _yappi._set_test_timings(_timings)
2694+ stats = utils.run_and_get_func_stats(a, )
2695+ stats.strip_dirs()
2696+ stats.save("tests/a1.pstats", type="pstat")
2697+ fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
2698+ fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
2699+ yappi.clear_stats()
2700+ _yappi._set_test_timings(_timings)
2701+ stats = utils.run_and_get_func_stats(a, )
2702+ stats.strip_dirs()
2703+ stats.save("tests/a2.pstats", type="pstat")
2704+ yappi.clear_stats()
2705+ _yappi._set_test_timings(_timings)
2706+ stats = utils.run_and_get_func_stats(b, )
2707+ stats.strip_dirs()
2708+ stats.save("tests/b1.pstats", type="pstat")
2709+ fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
2710+ yappi.clear_stats()
2711+ _yappi._set_test_timings(_timings)
2712+ stats = utils.run_and_get_func_stats(c, )
2713+ stats.strip_dirs()
2714+ stats.save("tests/c1.pstats", type="pstat")
2715+ fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
2716+
2717+ # merge saved stats and check pstats values are correct
2718+ import pstats
2719+ p = pstats.Stats(
2720+ 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
2721+ 'tests/c1.pstats'
2722+ )
2723+ p.strip_dirs()
2724+ # ct = ttot, tt = tsub
2725+ (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
2726+ self.assertEqual(cc, nc, 2)
2727+ self.assertEqual(tt, 20)
2728+ self.assertEqual(ct, 24)
2729+ (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
2730+ self.assertEqual(cc, nc, 3)
2731+ self.assertEqual(tt, 6)
2732+ self.assertEqual(ct, 6)
2733+ self.assertEqual(len(callers), 2)
2734+ (cc, nc, tt, ct) = callers[fsa_pid]
2735+ self.assertEqual(cc, nc, 2)
2736+ self.assertEqual(tt, 4)
2737+ self.assertEqual(ct, 4)
2738+ (cc, nc, tt, ct) = callers[fsb_pid]
2739+ self.assertEqual(cc, nc, 1)
2740+ self.assertEqual(tt, 2)
2741+ self.assertEqual(ct, 2)
2742+
2743+ def test_merge_stats(self):
2744+ _timings = {
2745+ "a_1": 15,
2746+ "b_1": 14,
2747+ "c_1": 12,
2748+ "d_1": 10,
2749+ "e_1": 9,
2750+ "f_1": 7,
2751+ "g_1": 6,
2752+ "h_1": 5,
2753+ "i_1": 1
2754+ }
2755+ _yappi._set_test_timings(_timings)
2756+
2757+ def a():
2758+ b()
2759+
2760+ def b():
2761+ c()
2762+
2763+ def c():
2764+ d()
2765+
2766+ def d():
2767+ e()
2768+
2769+ def e():
2770+ f()
2771+
2772+ def f():
2773+ g()
2774+
2775+ def g():
2776+ h()
2777+
2778+ def h():
2779+ i()
2780+
2781+ def i():
2782+ pass
2783+
2784+ yappi.start()
2785+ a()
2786+ a()
2787+ yappi.stop()
2788+ stats = yappi.get_func_stats()
2789+ self.assertRaises(
2790+ NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
2791+ )
2792+ stats.save("tests/ystats2.ys")
2793+ yappi.clear_stats()
2794+ _yappi._set_test_timings(_timings)
2795+ yappi.start()
2796+ a()
2797+ stats = yappi.get_func_stats().add("tests/ystats2.ys")
2798+ fsa = utils.find_stat_by_name(stats, "a")
2799+ fsb = utils.find_stat_by_name(stats, "b")
2800+ fsc = utils.find_stat_by_name(stats, "c")
2801+ fsd = utils.find_stat_by_name(stats, "d")
2802+ fse = utils.find_stat_by_name(stats, "e")
2803+ fsf = utils.find_stat_by_name(stats, "f")
2804+ fsg = utils.find_stat_by_name(stats, "g")
2805+ fsh = utils.find_stat_by_name(stats, "h")
2806+ fsi = utils.find_stat_by_name(stats, "i")
2807+ self.assertEqual(fsa.ttot, 45)
2808+ self.assertEqual(fsa.ncall, 3)
2809+ self.assertEqual(fsa.nactualcall, 3)
2810+ self.assertEqual(fsa.tsub, 3)
2811+ self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
2812+ self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
2813+ self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
2814+ self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
2815+ self.assertEqual(fsc.tsub, 6)
2816+ self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
2817+ self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
2818+ self.assertEqual(fsd.children[fse].ttot, fse.ttot)
2819+ self.assertEqual(fsd.children[fse].tsub, fse.tsub)
2820+ self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
2821+ self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
2822+ self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
2823+ self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
2824+ self.assertEqual(fsg.ttot, 18)
2825+ self.assertEqual(fsg.tsub, 3)
2826+ self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
2827+ self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
2828+ self.assertEqual(fsh.ttot, 15)
2829+ self.assertEqual(fsh.tsub, 12)
2830+ self.assertEqual(fsh.tavg, 5)
2831+ self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
2832+ self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
2833+ #stats.debug_print()
2834+
2835+ def test_merge_multithreaded_stats(self):
2836+ import _yappi
2837+ timings = {"a_1": 2, "b_1": 1}
2838+ _yappi._set_test_timings(timings)
2839+
2840+ def a():
2841+ pass
2842+
2843+ def b():
2844+ pass
2845+
2846+ yappi.start()
2847+ t = threading.Thread(target=a)
2848+ t.start()
2849+ t.join()
2850+ t = threading.Thread(target=b)
2851+ t.start()
2852+ t.join()
2853+ yappi.get_func_stats().save("tests/ystats1.ys")
2854+ yappi.clear_stats()
2855+ _yappi._set_test_timings(timings)
2856+ self.assertEqual(len(yappi.get_func_stats()), 0)
2857+ self.assertEqual(len(yappi.get_thread_stats()), 1)
2858+ t = threading.Thread(target=a)
2859+ t.start()
2860+ t.join()
2861+
2862+ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
2863+ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
2864+ yappi.get_func_stats().save("tests/ystats2.ys")
2865+
2866+ stats = yappi.YFuncStats([
2867+ "tests/ystats1.ys",
2868+ "tests/ystats2.ys",
2869+ ])
2870+ fsa = utils.find_stat_by_name(stats, "a")
2871+ fsb = utils.find_stat_by_name(stats, "b")
2872+ self.assertEqual(fsa.ncall, 2)
2873+ self.assertEqual(fsb.ncall, 1)
2874+ self.assertEqual(fsa.tsub, fsa.ttot, 4)
2875+ self.assertEqual(fsb.tsub, fsb.ttot, 1)
2876+
2877+ def test_merge_load_different_clock_types(self):
2878+ yappi.start(builtins=True)
2879+
2880+ def a():
2881+ b()
2882+
2883+ def b():
2884+ c()
2885+
2886+ def c():
2887+ pass
2888+
2889+ t = threading.Thread(target=a)
2890+ t.start()
2891+ t.join()
2892+ yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
2893+ yappi.stop()
2894+ yappi.clear_stats()
2895+ yappi.start(builtins=False)
2896+ t = threading.Thread(target=a)
2897+ t.start()
2898+ t.join()
2899+ yappi.get_func_stats().save("tests/ystats2.ys")
2900+ yappi.stop()
2901+ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
2902+ yappi.clear_stats()
2903+ yappi.set_clock_type("wall")
2904+ yappi.start()
2905+ t = threading.Thread(target=a)
2906+ t.start()
2907+ t.join()
2908+ yappi.get_func_stats().save("tests/ystats3.ys")
2909+ self.assertRaises(
2910+ yappi.YappiError,
2911+ yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
2912+ )
2913+ stats = yappi.YFuncStats(["tests/ystats1.ys",
2914+ "tests/ystats2.ys"]).sort("name")
2915+ fsa = utils.find_stat_by_name(stats, "a")
2916+ fsb = utils.find_stat_by_name(stats, "b")
2917+ fsc = utils.find_stat_by_name(stats, "c")
2918+ self.assertEqual(fsa.ncall, 2)
2919+ self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
2920+
2921+ def test_merge_aabab_aabbc(self):
2922+ _timings = {
2923+ "a_1": 15,
2924+ "a_2": 14,
2925+ "b_1": 12,
2926+ "a_3": 10,
2927+ "b_2": 9,
2928+ "c_1": 4
2929+ }
2930+ _yappi._set_test_timings(_timings)
2931+
2932+ def a():
2933+ if self._ncall == 1:
2934+ self._ncall += 1
2935+ a()
2936+ elif self._ncall == 5:
2937+ self._ncall += 1
2938+ a()
2939+ else:
2940+ b()
2941+
2942+ def b():
2943+ if self._ncall == 2:
2944+ self._ncall += 1
2945+ a()
2946+ elif self._ncall == 6:
2947+ self._ncall += 1
2948+ b()
2949+ elif self._ncall == 7:
2950+ c()
2951+ else:
2952+ return
2953+
2954+ def c():
2955+ pass
2956+
2957+ self._ncall = 1
2958+ stats = utils.run_and_get_func_stats(a, )
2959+ stats.save("tests/ystats1.ys")
2960+ yappi.clear_stats()
2961+ _yappi._set_test_timings(_timings)
2962+ #stats.print_all()
2963+
2964+ self._ncall = 5
2965+ stats = utils.run_and_get_func_stats(a, )
2966+ stats.save("tests/ystats2.ys")
2967+
2968+ #stats.print_all()
2969+
2970+ def a(): # same name but another function(code object)
2971+ pass
2972+
2973+ yappi.start()
2974+ a()
2975+ stats = yappi.get_func_stats().add(
2976+ ["tests/ystats1.ys", "tests/ystats2.ys"]
2977+ )
2978+ #stats.print_all()
2979+ self.assertEqual(len(stats), 4)
2980+
2981+ fsa = None
2982+ for stat in stats:
2983+ if stat.name == "a" and stat.ttot == 45:
2984+ fsa = stat
2985+ break
2986+ self.assertTrue(fsa is not None)
2987+
2988+ self.assertEqual(fsa.ncall, 7)
2989+ self.assertEqual(fsa.nactualcall, 3)
2990+ self.assertEqual(fsa.ttot, 45)
2991+ self.assertEqual(fsa.tsub, 10)
2992+ fsb = utils.find_stat_by_name(stats, "b")
2993+ fsc = utils.find_stat_by_name(stats, "c")
2994+ self.assertEqual(fsb.ncall, 6)
2995+ self.assertEqual(fsb.nactualcall, 3)
2996+ self.assertEqual(fsb.ttot, 36)
2997+ self.assertEqual(fsb.tsub, 27)
2998+ self.assertEqual(fsb.tavg, 6)
2999+ self.assertEqual(fsc.ttot, 8)
3000+ self.assertEqual(fsc.tsub, 8)
3001+ self.assertEqual(fsc.tavg, 4)
3002+ self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
3003+
3004+
3005+class MultithreadedScenarios(utils.YappiUnitTestCase):
3006+
3007+ def test_issue_32(self):
3008+ '''
3009+ Start yappi from different thread and we get Internal Error(15) as
3010+ the current_ctx_id() called while enumerating the threads in start()
3011+ and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
3012+ returns wrong object and thus sets an invalid id for the _ctx structure.
3013+
3014+ When this issue happens multiple Threads have same tid as the internal ts_ptr
3015+ will be same for different contexts. So, let's see if that happens
3016+ '''
3017+
3018+ def foo():
3019+ time.sleep(0.2)
3020+
3021+ def bar():
3022+ time.sleep(0.1)
3023+
3024+ def thread_func():
3025+ yappi.set_clock_type("wall")
3026+ yappi.start()
3027+
3028+ bar()
3029+
3030+ t = threading.Thread(target=thread_func)
3031+ t.start()
3032+ t.join()
3033+
3034+ foo()
3035+
3036+ yappi.stop()
3037+
3038+ thread_ids = set()
3039+ for tstat in yappi.get_thread_stats():
3040+ self.assertTrue(tstat.tid not in thread_ids)
3041+ thread_ids.add(tstat.tid)
3042+
3043+ def test_subsequent_profile(self):
3044+ WORKER_COUNT = 5
3045+
3046+ def a():
3047+ pass
3048+
3049+ def b():
3050+ pass
3051+
3052+ def c():
3053+ pass
3054+
3055+ _timings = {
3056+ "a_1": 3,
3057+ "b_1": 2,
3058+ "c_1": 1,
3059+ }
3060+
3061+ yappi.start()
3062+
3063+ def g():
3064+ pass
3065+
3066+ g()
3067+ yappi.stop()
3068+ yappi.clear_stats()
3069+ _yappi._set_test_timings(_timings)
3070+ yappi.start()
3071+
3072+ _dummy = []
3073+ for i in range(WORKER_COUNT):
3074+ t = threading.Thread(target=a)
3075+ t.start()
3076+ t.join()
3077+ for i in range(WORKER_COUNT):
3078+ t = threading.Thread(target=b)
3079+ t.start()
3080+ _dummy.append(t)
3081+ t.join()
3082+ for i in range(WORKER_COUNT):
3083+ t = threading.Thread(target=a)
3084+ t.start()
3085+ t.join()
3086+ for i in range(WORKER_COUNT):
3087+ t = threading.Thread(target=c)
3088+ t.start()
3089+ t.join()
3090+ yappi.stop()
3091+ yappi.start()
3092+
3093+ def f():
3094+ pass
3095+
3096+ f()
3097+ stats = yappi.get_func_stats()
3098+ fsa = utils.find_stat_by_name(stats, 'a')
3099+ fsb = utils.find_stat_by_name(stats, 'b')
3100+ fsc = utils.find_stat_by_name(stats, 'c')
3101+ self.assertEqual(fsa.ncall, 10)
3102+ self.assertEqual(fsb.ncall, 5)
3103+ self.assertEqual(fsc.ncall, 5)
3104+ self.assertEqual(fsa.ttot, fsa.tsub, 30)
3105+ self.assertEqual(fsb.ttot, fsb.tsub, 10)
3106+ self.assertEqual(fsc.ttot, fsc.tsub, 5)
3107+
3108+ # MACOSx optimizes by only creating one worker thread
3109+ self.assertTrue(len(yappi.get_thread_stats()) >= 2)
3110+
3111+ def test_basic(self):
3112+ yappi.set_clock_type('wall')
3113+
3114+ def dummy():
3115+ pass
3116+
3117+ def a():
3118+ time.sleep(0.2)
3119+
3120+ class Worker1(threading.Thread):
3121+
3122+ def a(self):
3123+ time.sleep(0.3)
3124+
3125+ def run(self):
3126+ self.a()
3127+
3128+ yappi.start(builtins=False, profile_threads=True)
3129+
3130+ c = Worker1()
3131+ c.start()
3132+ c.join()
3133+ a()
3134+ stats = yappi.get_func_stats()
3135+ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
3136+ fsa2 = utils.find_stat_by_name(stats, 'a')
3137+ self.assertTrue(fsa1 is not None)
3138+ self.assertTrue(fsa2 is not None)
3139+ self.assertTrue(fsa1.ttot > 0.2)
3140+ self.assertTrue(fsa2.ttot > 0.1)
3141+ tstats = yappi.get_thread_stats()
3142+ self.assertEqual(len(tstats), 2)
3143+ tsa = utils.find_stat_by_name(tstats, 'Worker1')
3144+ tsm = utils.find_stat_by_name(tstats, '_MainThread')
3145+ dummy() # call dummy to force ctx name to be retrieved again.
3146+ self.assertTrue(tsa is not None)
3147+ # TODO: I put dummy() to fix below, remove the comments after a while.
3148+ self.assertTrue( # FIX: I see this fails sometimes?
3149+ tsm is not None,
3150+ 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
3151+
3152+ def test_ctx_stats(self):
3153+ from threading import Thread
3154+ DUMMY_WORKER_COUNT = 5
3155+ yappi.start()
3156+
3157+ class DummyThread(Thread):
3158+ pass
3159+
3160+ def dummy():
3161+ pass
3162+
3163+ def dummy_worker():
3164+ pass
3165+
3166+ for i in range(DUMMY_WORKER_COUNT):
3167+ t = DummyThread(target=dummy_worker)
3168+ t.start()
3169+ t.join()
3170+ yappi.stop()
3171+ stats = yappi.get_thread_stats()
3172+ tsa = utils.find_stat_by_name(stats, "DummyThread")
3173+ self.assertTrue(tsa is not None)
3174+ yappi.clear_stats()
3175+ time.sleep(1.0)
3176+ _timings = {
3177+ "a_1": 6,
3178+ "b_1": 5,
3179+ "c_1": 3,
3180+ "d_1": 1,
3181+ "a_2": 4,
3182+ "b_2": 3,
3183+ "c_2": 2,
3184+ "d_2": 1
3185+ }
3186+ _yappi._set_test_timings(_timings)
3187+
3188+ class Thread1(Thread):
3189+ pass
3190+
3191+ class Thread2(Thread):
3192+ pass
3193+
3194+ def a():
3195+ b()
3196+
3197+ def b():
3198+ c()
3199+
3200+ def c():
3201+ d()
3202+
3203+ def d():
3204+ time.sleep(0.6)
3205+
3206+ yappi.set_clock_type("wall")
3207+ yappi.start()
3208+ t1 = Thread1(target=a)
3209+ t1.start()
3210+ t2 = Thread2(target=a)
3211+ t2.start()
3212+ t1.join()
3213+ t2.join()
3214+ stats = yappi.get_thread_stats()
3215+
3216+ # the fist clear_stats clears the context table?
3217+ tsa = utils.find_stat_by_name(stats, "DummyThread")
3218+ self.assertTrue(tsa is None)
3219+
3220+ tst1 = utils.find_stat_by_name(stats, "Thread1")
3221+ tst2 = utils.find_stat_by_name(stats, "Thread2")
3222+ tsmain = utils.find_stat_by_name(stats, "_MainThread")
3223+ dummy() # call dummy to force ctx name to be retrieved again.
3224+ self.assertTrue(len(stats) == 3)
3225+ self.assertTrue(tst1 is not None)
3226+ self.assertTrue(tst2 is not None)
3227+ # TODO: I put dummy() to fix below, remove the comments after a while.
3228+ self.assertTrue( # FIX: I see this fails sometimes
3229+ tsmain is not None,
3230+ 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
3231+ self.assertTrue(1.0 > tst2.ttot >= 0.5)
3232+ self.assertTrue(1.0 > tst1.ttot >= 0.5)
3233+
3234+ # test sorting of the ctx stats
3235+ stats = stats.sort("totaltime", "desc")
3236+ prev_stat = None
3237+ for stat in stats:
3238+ if prev_stat:
3239+ self.assertTrue(prev_stat.ttot >= stat.ttot)
3240+ prev_stat = stat
3241+ stats = stats.sort("totaltime", "asc")
3242+ prev_stat = None
3243+ for stat in stats:
3244+ if prev_stat:
3245+ self.assertTrue(prev_stat.ttot <= stat.ttot)
3246+ prev_stat = stat
3247+ stats = stats.sort("schedcount", "desc")
3248+ prev_stat = None
3249+ for stat in stats:
3250+ if prev_stat:
3251+ self.assertTrue(prev_stat.sched_count >= stat.sched_count)
3252+ prev_stat = stat
3253+ stats = stats.sort("name", "desc")
3254+ prev_stat = None
3255+ for stat in stats:
3256+ if prev_stat:
3257+ self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
3258+ prev_stat = stat
3259+ self.assertRaises(
3260+ yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
3261+ )
3262+ self.assertRaises(
3263+ yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
3264+ )
3265+
3266+ def test_ctx_stats_cpu(self):
3267+
3268+ def get_thread_name():
3269+ try:
3270+ return threading.current_thread().name
3271+ except AttributeError:
3272+ return "Anonymous"
3273+
3274+ def burn_cpu(sec):
3275+ t0 = yappi.get_clock_time()
3276+ elapsed = 0
3277+ while (elapsed < sec):
3278+ for _ in range(1000):
3279+ pass
3280+ elapsed = yappi.get_clock_time() - t0
3281+
3282+ def test():
3283+
3284+ ts = []
3285+ for i in (0.01, 0.05, 0.1):
3286+ t = threading.Thread(target=burn_cpu, args=(i, ))
3287+ t.name = "burn_cpu-%s" % str(i)
3288+ t.start()
3289+ ts.append(t)
3290+ for t in ts:
3291+ t.join()
3292+
3293+ yappi.set_clock_type("cpu")
3294+ yappi.set_context_name_callback(get_thread_name)
3295+
3296+ yappi.start()
3297+
3298+ test()
3299+
3300+ yappi.stop()
3301+
3302+ tstats = yappi.get_thread_stats()
3303+ r1 = '''
3304+ burn_cpu-0.1 3 123145356058624 0.100105 8
3305+ burn_cpu-0.05 2 123145361313792 0.050149 8
3306+ burn_cpu-0.01 1 123145356058624 0.010127 2
3307+ MainThread 0 4321620864 0.001632 6
3308+ '''
3309+ self.assert_ctx_stats_almost_equal(r1, tstats)
3310+
3311+ def test_producer_consumer_with_queues(self):
3312+ # we currently just stress yappi, no functionality test is done here.
3313+ yappi.start()
3314+ if utils.is_py3x():
3315+ from queue import Queue
3316+ else:
3317+ from Queue import Queue
3318+ from threading import Thread
3319+ WORKER_THREAD_COUNT = 50
3320+ WORK_ITEM_COUNT = 2000
3321+
3322+ def worker():
3323+ while True:
3324+ item = q.get()
3325+ # do the work with item
3326+ q.task_done()
3327+
3328+ q = Queue()
3329+ for i in range(WORKER_THREAD_COUNT):
3330+ t = Thread(target=worker)
3331+ t.daemon = True
3332+ t.start()
3333+
3334+ for item in range(WORK_ITEM_COUNT):
3335+ q.put(item)
3336+ q.join() # block until all tasks are done
3337+ #yappi.get_func_stats().sort("callcount").print_all()
3338+ yappi.stop()
3339+
3340+ def test_temporary_lock_waiting(self):
3341+ yappi.start()
3342+ _lock = threading.Lock()
3343+
3344+ def worker():
3345+ _lock.acquire()
3346+ try:
3347+ time.sleep(1.0)
3348+ finally:
3349+ _lock.release()
3350+
3351+ t1 = threading.Thread(target=worker)
3352+ t2 = threading.Thread(target=worker)
3353+ t1.start()
3354+ t2.start()
3355+ t1.join()
3356+ t2.join()
3357+ #yappi.get_func_stats().sort("callcount").print_all()
3358+ yappi.stop()
3359+
3360+ @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
3361+ def test_signals_with_blocking_calls(self):
3362+ import signal, os, time
3363+
3364+ # just to verify if signal is handled correctly and stats/yappi are not corrupted.
3365+ def handler(signum, frame):
3366+ raise Exception("Signal handler executed!")
3367+
3368+ yappi.start()
3369+ signal.signal(signal.SIGALRM, handler)
3370+ signal.alarm(1)
3371+ self.assertRaises(Exception, time.sleep, 2)
3372+ stats = yappi.get_func_stats()
3373+ fsh = utils.find_stat_by_name(stats, "handler")
3374+ self.assertTrue(fsh is not None)
3375+
3376+ @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
3377+ def test_concurrent_futures(self):
3378+ yappi.start()
3379+ from concurrent.futures import ThreadPoolExecutor
3380+ with ThreadPoolExecutor(max_workers=5) as executor:
3381+ f = executor.submit(pow, 5, 2)
3382+ self.assertEqual(f.result(), 25)
3383+ time.sleep(1.0)
3384+ yappi.stop()
3385+
3386+ @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
3387+ def test_barrier(self):
3388+ yappi.start()
3389+ b = threading.Barrier(2, timeout=1)
3390+
3391+ def worker():
3392+ try:
3393+ b.wait()
3394+ except threading.BrokenBarrierError:
3395+ pass
3396+ except Exception:
3397+ raise Exception("BrokenBarrierError not raised")
3398+
3399+ t1 = threading.Thread(target=worker)
3400+ t1.start()
3401+ #b.wait()
3402+ t1.join()
3403+ yappi.stop()
3404+
3405+
3406+class NonRecursiveFunctions(utils.YappiUnitTestCase):
3407+
3408+ def test_abcd(self):
3409+ _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
3410+ _yappi._set_test_timings(_timings)
3411+
3412+ def a():
3413+ b()
3414+
3415+ def b():
3416+ c()
3417+
3418+ def c():
3419+ d()
3420+
3421+ def d():
3422+ pass
3423+
3424+ stats = utils.run_and_get_func_stats(a)
3425+ fsa = utils.find_stat_by_name(stats, 'a')
3426+ fsb = utils.find_stat_by_name(stats, 'b')
3427+ fsc = utils.find_stat_by_name(stats, 'c')
3428+ fsd = utils.find_stat_by_name(stats, 'd')
3429+ cfsab = fsa.children[fsb]
3430+ cfsbc = fsb.children[fsc]
3431+ cfscd = fsc.children[fsd]
3432+
3433+ self.assertEqual(fsa.ttot, 6)
3434+ self.assertEqual(fsa.tsub, 1)
3435+ self.assertEqual(fsb.ttot, 5)
3436+ self.assertEqual(fsb.tsub, 2)
3437+ self.assertEqual(fsc.ttot, 3)
3438+ self.assertEqual(fsc.tsub, 2)
3439+ self.assertEqual(fsd.ttot, 1)
3440+ self.assertEqual(fsd.tsub, 1)
3441+ self.assertEqual(cfsab.ttot, 5)
3442+ self.assertEqual(cfsab.tsub, 2)
3443+ self.assertEqual(cfsbc.ttot, 3)
3444+ self.assertEqual(cfsbc.tsub, 2)
3445+ self.assertEqual(cfscd.ttot, 1)
3446+ self.assertEqual(cfscd.tsub, 1)
3447+
3448+ def test_stop_in_middle(self):
3449+ _timings = {"a_1": 6, "b_1": 4}
3450+ _yappi._set_test_timings(_timings)
3451+
3452+ def a():
3453+ b()
3454+ yappi.stop()
3455+
3456+ def b():
3457+ time.sleep(0.2)
3458+
3459+ yappi.start()
3460+ a()
3461+ stats = yappi.get_func_stats()
3462+ fsa = utils.find_stat_by_name(stats, 'a')
3463+ fsb = utils.find_stat_by_name(stats, 'b')
3464+
3465+ self.assertEqual(fsa.ncall, 1)
3466+ self.assertEqual(fsa.nactualcall, 0)
3467+ self.assertEqual(fsa.ttot, 0) # no call_leave called
3468+ self.assertEqual(fsa.tsub, 0) # no call_leave called
3469+ self.assertEqual(fsb.ttot, 4)
3470+
3471+
3472+class RecursiveFunctions(utils.YappiUnitTestCase):
3473+
3474+ def test_fibonacci(self):
3475+
3476+ def fib(n):
3477+ if n > 1:
3478+ return fib(n - 1) + fib(n - 2)
3479+ else:
3480+ return n
3481+
3482+ stats = utils.run_and_get_func_stats(fib, 22)
3483+ fs = utils.find_stat_by_name(stats, 'fib')
3484+ self.assertEqual(fs.ncall, 57313)
3485+ self.assertEqual(fs.ttot, fs.tsub)
3486+
3487+ def test_abcadc(self):
3488+ _timings = {
3489+ "a_1": 20,
3490+ "b_1": 19,
3491+ "c_1": 17,
3492+ "a_2": 13,
3493+ "d_1": 12,
3494+ "c_2": 10,
3495+ "a_3": 5
3496+ }
3497+ _yappi._set_test_timings(_timings)
3498+
3499+ def a(n):
3500+ if n == 3:
3501+ return
3502+ if n == 1 + 1:
3503+ d(n)
3504+ else:
3505+ b(n)
3506+
3507+ def b(n):
3508+ c(n)
3509+
3510+ def c(n):
3511+ a(n + 1)
3512+
3513+ def d(n):
3514+ c(n)
3515+
3516+ stats = utils.run_and_get_func_stats(a, 1)
3517+ fsa = utils.find_stat_by_name(stats, 'a')
3518+ fsb = utils.find_stat_by_name(stats, 'b')
3519+ fsc = utils.find_stat_by_name(stats, 'c')
3520+ fsd = utils.find_stat_by_name(stats, 'd')
3521+ self.assertEqual(fsa.ncall, 3)
3522+ self.assertEqual(fsa.nactualcall, 1)
3523+ self.assertEqual(fsa.ttot, 20)
3524+ self.assertEqual(fsa.tsub, 7)
3525+ self.assertEqual(fsb.ttot, 19)
3526+ self.assertEqual(fsb.tsub, 2)
3527+ self.assertEqual(fsc.ttot, 17)
3528+ self.assertEqual(fsc.tsub, 9)
3529+ self.assertEqual(fsd.ttot, 12)
3530+ self.assertEqual(fsd.tsub, 2)
3531+ cfsca = fsc.children[fsa]
3532+ self.assertEqual(cfsca.nactualcall, 0)
3533+ self.assertEqual(cfsca.ncall, 2)
3534+ self.assertEqual(cfsca.ttot, 13)
3535+ self.assertEqual(cfsca.tsub, 6)
3536+
3537+ def test_aaaa(self):
3538+ _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
3539+ _yappi._set_test_timings(_timings)
3540+
3541+ def d(n):
3542+ if n == 3:
3543+ return
3544+ d(n + 1)
3545+
3546+ stats = utils.run_and_get_func_stats(d, 0)
3547+ fsd = utils.find_stat_by_name(stats, 'd')
3548+ self.assertEqual(fsd.ncall, 4)
3549+ self.assertEqual(fsd.nactualcall, 1)
3550+ self.assertEqual(fsd.ttot, 9)
3551+ self.assertEqual(fsd.tsub, 9)
3552+ cfsdd = fsd.children[fsd]
3553+ self.assertEqual(cfsdd.ttot, 7)
3554+ self.assertEqual(cfsdd.tsub, 7)
3555+ self.assertEqual(cfsdd.ncall, 3)
3556+ self.assertEqual(cfsdd.nactualcall, 0)
3557+
3558+ def test_abcabc(self):
3559+ _timings = {
3560+ "a_1": 20,
3561+ "b_1": 19,
3562+ "c_1": 17,
3563+ "a_2": 13,
3564+ "b_2": 11,
3565+ "c_2": 9,
3566+ "a_3": 6
3567+ }
3568+ _yappi._set_test_timings(_timings)
3569+
3570+ def a(n):
3571+ if n == 3:
3572+ return
3573+ else:
3574+ b(n)
3575+
3576+ def b(n):
3577+ c(n)
3578+
3579+ def c(n):
3580+ a(n + 1)
3581+
3582+ stats = utils.run_and_get_func_stats(a, 1)
3583+ fsa = utils.find_stat_by_name(stats, 'a')
3584+ fsb = utils.find_stat_by_name(stats, 'b')
3585+ fsc = utils.find_stat_by_name(stats, 'c')
3586+ self.assertEqual(fsa.ncall, 3)
3587+ self.assertEqual(fsa.nactualcall, 1)
3588+ self.assertEqual(fsa.ttot, 20)
3589+ self.assertEqual(fsa.tsub, 9)
3590+ self.assertEqual(fsb.ttot, 19)
3591+ self.assertEqual(fsb.tsub, 4)
3592+ self.assertEqual(fsc.ttot, 17)
3593+ self.assertEqual(fsc.tsub, 7)
3594+ cfsab = fsa.children[fsb]
3595+ cfsbc = fsb.children[fsc]
3596+ cfsca = fsc.children[fsa]
3597+ self.assertEqual(cfsab.ttot, 19)
3598+ self.assertEqual(cfsab.tsub, 4)
3599+ self.assertEqual(cfsbc.ttot, 17)
3600+ self.assertEqual(cfsbc.tsub, 7)
3601+ self.assertEqual(cfsca.ttot, 13)
3602+ self.assertEqual(cfsca.tsub, 8)
3603+
3604+ def test_abcbca(self):
3605+ _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
3606+ _yappi._set_test_timings(_timings)
3607+ self._ncall = 1
3608+
3609+ def a():
3610+ if self._ncall == 1:
3611+ b()
3612+ else:
3613+ return
3614+
3615+ def b():
3616+ c()
3617+
3618+ def c():
3619+ if self._ncall == 1:
3620+ self._ncall += 1
3621+ b()
3622+ else:
3623+ a()
3624+
3625+ stats = utils.run_and_get_func_stats(a)
3626+ fsa = utils.find_stat_by_name(stats, 'a')
3627+ fsb = utils.find_stat_by_name(stats, 'b')
3628+ fsc = utils.find_stat_by_name(stats, 'c')
3629+ cfsab = fsa.children[fsb]
3630+ cfsbc = fsb.children[fsc]
3631+ cfsca = fsc.children[fsa]
3632+ self.assertEqual(fsa.ttot, 10)
3633+ self.assertEqual(fsa.tsub, 2)
3634+ self.assertEqual(fsb.ttot, 9)
3635+ self.assertEqual(fsb.tsub, 4)
3636+ self.assertEqual(fsc.ttot, 7)
3637+ self.assertEqual(fsc.tsub, 4)
3638+ self.assertEqual(cfsab.ttot, 9)
3639+ self.assertEqual(cfsab.tsub, 2)
3640+ self.assertEqual(cfsbc.ttot, 7)
3641+ self.assertEqual(cfsbc.tsub, 4)
3642+ self.assertEqual(cfsca.ttot, 1)
3643+ self.assertEqual(cfsca.tsub, 1)
3644+ self.assertEqual(cfsca.ncall, 1)
3645+ self.assertEqual(cfsca.nactualcall, 0)
3646+
3647+ def test_aabccb(self):
3648+ _timings = {
3649+ "a_1": 13,
3650+ "a_2": 11,
3651+ "b_1": 9,
3652+ "c_1": 5,
3653+ "c_2": 3,
3654+ "b_2": 1
3655+ }
3656+ _yappi._set_test_timings(_timings)
3657+ self._ncall = 1
3658+
3659+ def a():
3660+ if self._ncall == 1:
3661+ self._ncall += 1
3662+ a()
3663+ else:
3664+ b()
3665+
3666+ def b():
3667+ if self._ncall == 3:
3668+ return
3669+ else:
3670+ c()
3671+
3672+ def c():
3673+ if self._ncall == 2:
3674+ self._ncall += 1
3675+ c()
3676+ else:
3677+ b()
3678+
3679+ stats = utils.run_and_get_func_stats(a)
3680+ fsa = utils.find_stat_by_name(stats, 'a')
3681+ fsb = utils.find_stat_by_name(stats, 'b')
3682+ fsc = utils.find_stat_by_name(stats, 'c')
3683+ cfsaa = fsa.children[fsa.index]
3684+ cfsab = fsa.children[fsb]
3685+ cfsbc = fsb.children[fsc.full_name]
3686+ cfscc = fsc.children[fsc]
3687+ cfscb = fsc.children[fsb]
3688+ self.assertEqual(fsb.ttot, 9)
3689+ self.assertEqual(fsb.tsub, 5)
3690+ self.assertEqual(cfsbc.ttot, 5)
3691+ self.assertEqual(cfsbc.tsub, 2)
3692+ self.assertEqual(fsa.ttot, 13)
3693+ self.assertEqual(fsa.tsub, 4)
3694+ self.assertEqual(cfsab.ttot, 9)
3695+ self.assertEqual(cfsab.tsub, 4)
3696+ self.assertEqual(cfsaa.ttot, 11)
3697+ self.assertEqual(cfsaa.tsub, 2)
3698+ self.assertEqual(fsc.ttot, 5)
3699+ self.assertEqual(fsc.tsub, 4)
3700+
3701+ def test_abaa(self):
3702+ _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
3703+ _yappi._set_test_timings(_timings)
3704+
3705+ self._ncall = 1
3706+
3707+ def a():
3708+ if self._ncall == 1:
3709+ b()
3710+ elif self._ncall == 2:
3711+ self._ncall += 1
3712+ a()
3713+ else:
3714+ return
3715+
3716+ def b():
3717+ self._ncall += 1
3718+ a()
3719+
3720+ stats = utils.run_and_get_func_stats(a)
3721+ fsa = utils.find_stat_by_name(stats, 'a')
3722+ fsb = utils.find_stat_by_name(stats, 'b')
3723+ cfsaa = fsa.children[fsa]
3724+ cfsba = fsb.children[fsa]
3725+ self.assertEqual(fsb.ttot, 10)
3726+ self.assertEqual(fsb.tsub, 1)
3727+ self.assertEqual(fsa.ttot, 13)
3728+ self.assertEqual(fsa.tsub, 12)
3729+ self.assertEqual(cfsaa.ttot, 5)
3730+ self.assertEqual(cfsaa.tsub, 5)
3731+ self.assertEqual(cfsba.ttot, 9)
3732+ self.assertEqual(cfsba.tsub, 4)
3733+
3734+ def test_aabb(self):
3735+ _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
3736+ _yappi._set_test_timings(_timings)
3737+
3738+ self._ncall = 1
3739+
3740+ def a():
3741+ if self._ncall == 1:
3742+ self._ncall += 1
3743+ a()
3744+ elif self._ncall == 2:
3745+ b()
3746+ else:
3747+ return
3748+
3749+ def b():
3750+ if self._ncall == 2:
3751+ self._ncall += 1
3752+ b()
3753+ else:
3754+ return
3755+
3756+ stats = utils.run_and_get_func_stats(a)
3757+ fsa = utils.find_stat_by_name(stats, 'a')
3758+ fsb = utils.find_stat_by_name(stats, 'b')
3759+ cfsaa = fsa.children[fsa]
3760+ cfsab = fsa.children[fsb]
3761+ cfsbb = fsb.children[fsb]
3762+ self.assertEqual(fsa.ttot, 13)
3763+ self.assertEqual(fsa.tsub, 4)
3764+ self.assertEqual(fsb.ttot, 9)
3765+ self.assertEqual(fsb.tsub, 9)
3766+ self.assertEqual(cfsaa.ttot, 10)
3767+ self.assertEqual(cfsaa.tsub, 1)
3768+ self.assertEqual(cfsab.ttot, 9)
3769+ self.assertEqual(cfsab.tsub, 4)
3770+ self.assertEqual(cfsbb.ttot, 5)
3771+ self.assertEqual(cfsbb.tsub, 5)
3772+
3773+ def test_abbb(self):
3774+ _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
3775+ _yappi._set_test_timings(_timings)
3776+
3777+ self._ncall = 1
3778+
3779+ def a():
3780+ if self._ncall == 1:
3781+ b()
3782+
3783+ def b():
3784+ if self._ncall == 3:
3785+ return
3786+ self._ncall += 1
3787+ b()
3788+
3789+ stats = utils.run_and_get_func_stats(a)
3790+ fsa = utils.find_stat_by_name(stats, 'a')
3791+ fsb = utils.find_stat_by_name(stats, 'b')
3792+ cfsab = fsa.children[fsb]
3793+ cfsbb = fsb.children[fsb]
3794+ self.assertEqual(fsa.ttot, 13)
3795+ self.assertEqual(fsa.tsub, 3)
3796+ self.assertEqual(fsb.ttot, 10)
3797+ self.assertEqual(fsb.tsub, 10)
3798+ self.assertEqual(fsb.ncall, 3)
3799+ self.assertEqual(fsb.nactualcall, 1)
3800+ self.assertEqual(cfsab.ttot, 10)
3801+ self.assertEqual(cfsab.tsub, 4)
3802+ self.assertEqual(cfsbb.ttot, 6)
3803+ self.assertEqual(cfsbb.tsub, 6)
3804+ self.assertEqual(cfsbb.nactualcall, 0)
3805+ self.assertEqual(cfsbb.ncall, 2)
3806+
3807+ def test_aaab(self):
3808+ _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
3809+ _yappi._set_test_timings(_timings)
3810+
3811+ self._ncall = 1
3812+
3813+ def a():
3814+ if self._ncall == 3:
3815+ b()
3816+ return
3817+ self._ncall += 1
3818+ a()
3819+
3820+ def b():
3821+ return
3822+
3823+ stats = utils.run_and_get_func_stats(a)
3824+ fsa = utils.find_stat_by_name(stats, 'a')
3825+ fsb = utils.find_stat_by_name(stats, 'b')
3826+ cfsaa = fsa.children[fsa]
3827+ cfsab = fsa.children[fsb]
3828+ self.assertEqual(fsa.ttot, 13)
3829+ self.assertEqual(fsa.tsub, 12)
3830+ self.assertEqual(fsb.ttot, 1)
3831+ self.assertEqual(fsb.tsub, 1)
3832+ self.assertEqual(cfsaa.ttot, 10)
3833+ self.assertEqual(cfsaa.tsub, 9)
3834+ self.assertEqual(cfsab.ttot, 1)
3835+ self.assertEqual(cfsab.tsub, 1)
3836+
3837+ def test_abab(self):
3838+ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
3839+ _yappi._set_test_timings(_timings)
3840+
3841+ self._ncall = 1
3842+
3843+ def a():
3844+ b()
3845+
3846+ def b():
3847+ if self._ncall == 2:
3848+ return
3849+ self._ncall += 1
3850+ a()
3851+
3852+ stats = utils.run_and_get_func_stats(a)
3853+ fsa = utils.find_stat_by_name(stats, 'a')
3854+ fsb = utils.find_stat_by_name(stats, 'b')
3855+ cfsab = fsa.children[fsb]
3856+ cfsba = fsb.children[fsa]
3857+ self.assertEqual(fsa.ttot, 13)
3858+ self.assertEqual(fsa.tsub, 8)
3859+ self.assertEqual(fsb.ttot, 10)
3860+ self.assertEqual(fsb.tsub, 5)
3861+ self.assertEqual(cfsab.ttot, 10)
3862+ self.assertEqual(cfsab.tsub, 5)
3863+ self.assertEqual(cfsab.ncall, 2)
3864+ self.assertEqual(cfsab.nactualcall, 1)
3865+ self.assertEqual(cfsba.ttot, 6)
3866+ self.assertEqual(cfsba.tsub, 5)
3867+
3868+
3869+if __name__ == '__main__':
3870+ # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
3871+ # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
3872+ unittest.main()
3873--- a/tests/test_gevent.py
3874+++ b/tests/test_gevent.py
3875@@ -4,7 +4,7 @@ import yappi
3876 import gevent
3877 from gevent.event import Event
3878 import threading
3879-from utils import (
3880+from .utils import (
3881 YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io,
3882 burn_io_gevent
3883 )
3884--- a/tests/test_hooks.py
3885+++ b/tests/test_hooks.py
3886@@ -5,7 +5,7 @@ import unittest
3887 import time
3888
3889 import yappi
3890-import utils
3891+import tests.utils as utils
3892
3893
3894 def a():
3895--- a/tests/test_tags.py
3896+++ b/tests/test_tags.py
3897@@ -2,7 +2,7 @@ import unittest
3898 import yappi
3899 import threading
3900 import time
3901-from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
3902+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
3903
3904
3905 class MultiThreadTests(YappiUnitTestCase):