Skip to content

gh-124402: Speed up test_free_threading and test_super #124491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 30 additions & 37 deletions Lib/test/test_free_threading/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
from threading import Thread
from unittest import TestCase

from test import support
from test.support import threading_helper


NTHREAD = 10
OBJECT_COUNT = 5_000


class C:
def __init__(self, v):
self.v = v


@threading_helper.requires_working_threading()
class TestList(TestCase):
@support.requires_resource('cpu')
def test_racing_iter_append(self):

l = []
OBJECT_COUNT = 10000

def writer_func():
for i in range(OBJECT_COUNT):
Expand All @@ -34,7 +34,7 @@ def reader_func():

writer = Thread(target=writer_func)
readers = []
for x in range(30):
for x in range(NTHREAD):
reader = Thread(target=reader_func)
readers.append(reader)
reader.start()
Expand All @@ -44,39 +44,32 @@ def reader_func():
for reader in readers:
reader.join()

@support.requires_resource('cpu')
def test_racing_iter_extend(self):
iters = [
lambda x: [x],
]
for iter_case in iters:
with self.subTest(iter=iter_case):
l = []
OBJECT_COUNT = 10000

def writer_func():
for i in range(OBJECT_COUNT):
l.extend(iter_case(C(i + OBJECT_COUNT)))

def reader_func():
while True:
count = len(l)
for i, x in enumerate(l):
self.assertEqual(x.v, i + OBJECT_COUNT)
if count == OBJECT_COUNT:
break

writer = Thread(target=writer_func)
readers = []
for x in range(30):
reader = Thread(target=reader_func)
readers.append(reader)
reader.start()

writer.start()
writer.join()
for reader in readers:
reader.join()
l = []

def writer_func():
for i in range(OBJECT_COUNT):
l.extend([C(i + OBJECT_COUNT)])

def reader_func():
while True:
count = len(l)
for i, x in enumerate(l):
self.assertEqual(x.v, i + OBJECT_COUNT)
if count == OBJECT_COUNT:
break

writer = Thread(target=writer_func)
readers = []
for x in range(NTHREAD):
reader = Thread(target=reader_func)
readers.append(reader)
reader.start()

writer.start()
writer.join()
for reader in readers:
reader.join()


if __name__ == "__main__":
Expand Down
14 changes: 7 additions & 7 deletions Lib/test/test_free_threading/test_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
import weakref

from sys import monitoring
from test import support
from test.support import threading_helper
from threading import Thread, _PyRLock
from unittest import TestCase


class InstrumentationMultiThreadedMixin:
thread_count = 10
func_count = 200
func_count = 50
fib = 12

def after_threads(self):
Expand All @@ -37,14 +36,13 @@ def work(self, n, funcs):
def start_work(self, n, funcs):
# 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.
time.sleep(1)
time.sleep(0.1)
self.work(n, funcs)

def after_test(self):
"""Runs once after the test is done"""
pass

@support.requires_resource('cpu')
def test_instrumentation(self):
# Setup a bunch of functions which will need instrumentation...
funcs = []
Expand Down Expand Up @@ -220,29 +218,31 @@ def test_register_callback(self):
for ref in self.refs:
self.assertEqual(ref(), None)

@support.requires_resource('cpu')
def test_set_local_trace_opcodes(self):
def trace(frame, event, arg):
frame.f_trace_opcodes = True
return trace

loops = 1_000

sys.settrace(trace)
try:
l = _PyRLock()

def f():
for i in range(3000):
for i in range(loops):
with l:
pass

t = Thread(target=f)
t.start()
for i in range(3000):
for i in range(loops):
with l:
pass
t.join()
finally:
sys.settrace(None)


if __name__ == "__main__":
unittest.main()
6 changes: 3 additions & 3 deletions Lib/test/test_free_threading/test_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from threading import Thread
from unittest import TestCase

from test import support
from test.support import threading_helper


Expand Down Expand Up @@ -97,8 +96,9 @@ def reader_func():

self.run_one(writer_func, reader_func)

@support.requires_resource('cpu')
def test___class___modification(self):
loops = 200

class Foo:
pass

Expand All @@ -108,7 +108,7 @@ class Bar:
thing = Foo()
def work():
foo = thing
for _ in range(5000):
for _ in range(loops):
foo.__class__ = Bar
type(foo)
foo.__class__ = Foo
Expand Down
7 changes: 1 addition & 6 deletions Lib/test/test_super.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import threading
import unittest
from unittest.mock import patch
from test import support
from test.support import import_helper, threading_helper


Expand Down Expand Up @@ -515,10 +514,6 @@ def test___class___modification_multithreaded(self):
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:
pass

Expand All @@ -528,7 +523,7 @@ class Bar:
thing = Foo()
def work():
foo = thing
for _ in range(5000):
for _ in range(200):
foo.__class__ = Bar
type(foo)
foo.__class__ = Foo
Expand Down
Loading