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