mirror of https://github.com/python/cpython
gh-124402: Speed up test_free_threading and test_super (#124491)
* Reduce the number of iterations and the number of threads so a whole test file takes less than a minute. * Refactor test_racing_iter_extend() to remove two levels of indentation. * test_monitoring() uses a sleep of 100 ms instead of 1 second.
This commit is contained in:
parent
08a467b537
commit
0387c34f7c
|
@ -3,10 +3,13 @@ import unittest
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from test import support
|
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
|
|
||||||
|
|
||||||
|
NTHREAD = 10
|
||||||
|
OBJECT_COUNT = 5_000
|
||||||
|
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
def __init__(self, v):
|
def __init__(self, v):
|
||||||
self.v = v
|
self.v = v
|
||||||
|
@ -14,11 +17,8 @@ class C:
|
||||||
|
|
||||||
@threading_helper.requires_working_threading()
|
@threading_helper.requires_working_threading()
|
||||||
class TestList(TestCase):
|
class TestList(TestCase):
|
||||||
@support.requires_resource('cpu')
|
|
||||||
def test_racing_iter_append(self):
|
def test_racing_iter_append(self):
|
||||||
|
|
||||||
l = []
|
l = []
|
||||||
OBJECT_COUNT = 10000
|
|
||||||
|
|
||||||
def writer_func():
|
def writer_func():
|
||||||
for i in range(OBJECT_COUNT):
|
for i in range(OBJECT_COUNT):
|
||||||
|
@ -34,7 +34,7 @@ class TestList(TestCase):
|
||||||
|
|
||||||
writer = Thread(target=writer_func)
|
writer = Thread(target=writer_func)
|
||||||
readers = []
|
readers = []
|
||||||
for x in range(30):
|
for x in range(NTHREAD):
|
||||||
reader = Thread(target=reader_func)
|
reader = Thread(target=reader_func)
|
||||||
readers.append(reader)
|
readers.append(reader)
|
||||||
reader.start()
|
reader.start()
|
||||||
|
@ -44,19 +44,12 @@ class TestList(TestCase):
|
||||||
for reader in readers:
|
for reader in readers:
|
||||||
reader.join()
|
reader.join()
|
||||||
|
|
||||||
@support.requires_resource('cpu')
|
|
||||||
def test_racing_iter_extend(self):
|
def test_racing_iter_extend(self):
|
||||||
iters = [
|
|
||||||
lambda x: [x],
|
|
||||||
]
|
|
||||||
for iter_case in iters:
|
|
||||||
with self.subTest(iter=iter_case):
|
|
||||||
l = []
|
l = []
|
||||||
OBJECT_COUNT = 10000
|
|
||||||
|
|
||||||
def writer_func():
|
def writer_func():
|
||||||
for i in range(OBJECT_COUNT):
|
for i in range(OBJECT_COUNT):
|
||||||
l.extend(iter_case(C(i + OBJECT_COUNT)))
|
l.extend([C(i + OBJECT_COUNT)])
|
||||||
|
|
||||||
def reader_func():
|
def reader_func():
|
||||||
while True:
|
while True:
|
||||||
|
@ -68,7 +61,7 @@ class TestList(TestCase):
|
||||||
|
|
||||||
writer = Thread(target=writer_func)
|
writer = Thread(target=writer_func)
|
||||||
readers = []
|
readers = []
|
||||||
for x in range(30):
|
for x in range(NTHREAD):
|
||||||
reader = Thread(target=reader_func)
|
reader = Thread(target=reader_func)
|
||||||
readers.append(reader)
|
readers.append(reader)
|
||||||
reader.start()
|
reader.start()
|
||||||
|
|
|
@ -7,7 +7,6 @@ import unittest
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from sys import monitoring
|
from sys import monitoring
|
||||||
from test import support
|
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
from threading import Thread, _PyRLock
|
from threading import Thread, _PyRLock
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
@ -15,7 +14,7 @@ from unittest import TestCase
|
||||||
|
|
||||||
class InstrumentationMultiThreadedMixin:
|
class InstrumentationMultiThreadedMixin:
|
||||||
thread_count = 10
|
thread_count = 10
|
||||||
func_count = 200
|
func_count = 50
|
||||||
fib = 12
|
fib = 12
|
||||||
|
|
||||||
def after_threads(self):
|
def after_threads(self):
|
||||||
|
@ -37,14 +36,13 @@ class InstrumentationMultiThreadedMixin:
|
||||||
def start_work(self, n, funcs):
|
def start_work(self, n, funcs):
|
||||||
# With the GIL builds we need to make sure that the hooks have
|
# With the GIL builds we need to make sure that the hooks have
|
||||||
# a chance to run as it's possible to run w/o releasing the GIL.
|
# a chance to run as it's possible to run w/o releasing the GIL.
|
||||||
time.sleep(1)
|
time.sleep(0.1)
|
||||||
self.work(n, funcs)
|
self.work(n, funcs)
|
||||||
|
|
||||||
def after_test(self):
|
def after_test(self):
|
||||||
"""Runs once after the test is done"""
|
"""Runs once after the test is done"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@support.requires_resource('cpu')
|
|
||||||
def test_instrumentation(self):
|
def test_instrumentation(self):
|
||||||
# Setup a bunch of functions which will need instrumentation...
|
# Setup a bunch of functions which will need instrumentation...
|
||||||
funcs = []
|
funcs = []
|
||||||
|
@ -220,29 +218,31 @@ class MonitoringMisc(MonitoringTestMixin, TestCase):
|
||||||
for ref in self.refs:
|
for ref in self.refs:
|
||||||
self.assertEqual(ref(), None)
|
self.assertEqual(ref(), None)
|
||||||
|
|
||||||
@support.requires_resource('cpu')
|
|
||||||
def test_set_local_trace_opcodes(self):
|
def test_set_local_trace_opcodes(self):
|
||||||
def trace(frame, event, arg):
|
def trace(frame, event, arg):
|
||||||
frame.f_trace_opcodes = True
|
frame.f_trace_opcodes = True
|
||||||
return trace
|
return trace
|
||||||
|
|
||||||
|
loops = 1_000
|
||||||
|
|
||||||
sys.settrace(trace)
|
sys.settrace(trace)
|
||||||
try:
|
try:
|
||||||
l = _PyRLock()
|
l = _PyRLock()
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
for i in range(3000):
|
for i in range(loops):
|
||||||
with l:
|
with l:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
t = Thread(target=f)
|
t = Thread(target=f)
|
||||||
t.start()
|
t.start()
|
||||||
for i in range(3000):
|
for i in range(loops):
|
||||||
with l:
|
with l:
|
||||||
pass
|
pass
|
||||||
t.join()
|
t.join()
|
||||||
finally:
|
finally:
|
||||||
sys.settrace(None)
|
sys.settrace(None)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -5,7 +5,6 @@ from concurrent.futures import ThreadPoolExecutor
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from test import support
|
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,8 +96,9 @@ class TestType(TestCase):
|
||||||
|
|
||||||
self.run_one(writer_func, reader_func)
|
self.run_one(writer_func, reader_func)
|
||||||
|
|
||||||
@support.requires_resource('cpu')
|
|
||||||
def test___class___modification(self):
|
def test___class___modification(self):
|
||||||
|
loops = 200
|
||||||
|
|
||||||
class Foo:
|
class Foo:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ class TestType(TestCase):
|
||||||
thing = Foo()
|
thing = Foo()
|
||||||
def work():
|
def work():
|
||||||
foo = thing
|
foo = thing
|
||||||
for _ in range(5000):
|
for _ in range(loops):
|
||||||
foo.__class__ = Bar
|
foo.__class__ = Bar
|
||||||
type(foo)
|
type(foo)
|
||||||
foo.__class__ = Foo
|
foo.__class__ = Foo
|
||||||
|
|
|
@ -4,7 +4,6 @@ import textwrap
|
||||||
import threading
|
import threading
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from test import support
|
|
||||||
from test.support import import_helper, threading_helper
|
from test.support import import_helper, threading_helper
|
||||||
|
|
||||||
|
|
||||||
|
@ -515,10 +514,6 @@ class TestSuper(unittest.TestCase):
|
||||||
an audit hook.
|
an audit hook.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if support.Py_GIL_DISABLED:
|
|
||||||
# gh-124402: On a Free Threaded build, the test takes a few minutes
|
|
||||||
support.requires('cpu')
|
|
||||||
|
|
||||||
class Foo:
|
class Foo:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -528,7 +523,7 @@ class TestSuper(unittest.TestCase):
|
||||||
thing = Foo()
|
thing = Foo()
|
||||||
def work():
|
def work():
|
||||||
foo = thing
|
foo = thing
|
||||||
for _ in range(5000):
|
for _ in range(200):
|
||||||
foo.__class__ = Bar
|
foo.__class__ = Bar
|
||||||
type(foo)
|
type(foo)
|
||||||
foo.__class__ = Foo
|
foo.__class__ = Foo
|
||||||
|
|
Loading…
Reference in New Issue