| import unittest |
| |
| from test.support import threading_helper |
| |
| import cProfile |
| import pstats |
| |
| |
| NTHREADS = 10 |
| INSERT_PER_THREAD = 1000 |
| |
| |
| @threading_helper.requires_working_threading() |
| class TestCProfile(unittest.TestCase): |
| def test_cprofile_racing_list_insert(self): |
| def list_insert(lst): |
| for i in range(INSERT_PER_THREAD): |
| lst.insert(0, i) |
| |
| lst = [] |
| |
| with cProfile.Profile() as pr: |
| threading_helper.run_concurrently( |
| worker_func=list_insert, nthreads=NTHREADS, args=(lst,) |
| ) |
| pr.create_stats() |
| ps = pstats.Stats(pr) |
| stats_profile = ps.get_stats_profile() |
| list_insert_profile = stats_profile.func_profiles[ |
| "<method 'insert' of 'list' objects>" |
| ] |
| # Even though there is no explicit recursive call to insert, |
| # cProfile may record some calls as recursive due to limitations |
| # in its handling of multithreaded programs. This issue is not |
| # directly related to FT Python itself; however, it tends to be |
| # more noticeable when using FT Python. Therefore, consider only |
| # the calls section and disregard the recursive part. |
| list_insert_ncalls = list_insert_profile.ncalls.split("/")[0] |
| self.assertEqual( |
| int(list_insert_ncalls), NTHREADS * INSERT_PER_THREAD |
| ) |
| |
| self.assertEqual(len(lst), NTHREADS * INSERT_PER_THREAD) |