Closes #21527: Add default number of workers to ThreadPoolExecutor. (Claudiu Popa.)
diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py
index 8d6081c..3ae442d 100644
--- a/Lib/concurrent/futures/thread.py
+++ b/Lib/concurrent/futures/thread.py
@@ -10,6 +10,7 @@
import queue
import threading
import weakref
+import os
# Workers are created as daemon threads. This is done to allow the interpreter
# to exit when there are still idle threads in a ThreadPoolExecutor's thread
@@ -80,13 +81,17 @@
_base.LOGGER.critical('Exception in worker', exc_info=True)
class ThreadPoolExecutor(_base.Executor):
- def __init__(self, max_workers):
+ def __init__(self, max_workers=None):
"""Initializes a new ThreadPoolExecutor instance.
Args:
max_workers: The maximum number of threads that can be used to
execute the given calls.
"""
+ if max_workers is None:
+ # Use this number because ThreadPoolExecutor is often
+ # used to overlap I/O instead of CPU work.
+ max_workers = (os.cpu_count() or 1) * 5
if max_workers <= 0:
raise ValueError("max_workers must be greater than 0")
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
index 83184c3..11560e6 100644
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -11,6 +11,7 @@
from test.script_helper import assert_python_ok
+import os
import sys
import threading
import time
@@ -444,6 +445,11 @@
self.executor.shutdown(wait=True)
self.assertCountEqual(finished, range(10))
+ def test_default_workers(self):
+ executor = self.executor_type()
+ self.assertEqual(executor._max_workers,
+ (os.cpu_count() or 1) * 5)
+
class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest, unittest.TestCase):
def test_killed_child(self):