]> granicus.if.org Git - python/commitdiff
Closes #21527: Add default number of workers to ThreadPoolExecutor. (Claudiu Popa.)
authorGuido van Rossum <guido@python.org>
Tue, 2 Sep 2014 17:39:18 +0000 (10:39 -0700)
committerGuido van Rossum <guido@python.org>
Tue, 2 Sep 2014 17:39:18 +0000 (10:39 -0700)
Doc/library/concurrent.futures.rst
Lib/concurrent/futures/thread.py
Lib/test/test_concurrent_futures.py
Misc/NEWS

index 08c926a6d4c99417f5c2d2d0685731b660d585ad..e487817dfb050ad83952b3efe66ca7e4c10b7128 100644 (file)
@@ -115,11 +115,19 @@ And::
    executor.submit(wait_on_future)
 
 
-.. class:: ThreadPoolExecutor(max_workers)
+.. class:: ThreadPoolExecutor(max_workers=None)
 
    An :class:`Executor` subclass that uses a pool of at most *max_workers*
    threads to execute calls asynchronously.
 
+   .. versionchanged:: 3.5
+      If *max_workers* is ``None`` or
+      not given, it will default to the number of processors on the machine,
+      multiplied by ``5``, assuming that :class:`ThreadPoolExecutor` is often
+      used to overlap I/O instead of CPU work and the number of workers
+      should be higher than the number of workers
+      for :class:`ProcessPoolExecutor`.
+
 
 .. _threadpoolexecutor-example:
 
index 8d6081cf15a56b9ad05d3ae97ef3c1e4f9afd1ba..3ae442d98703f5597b7f82b9781f169b533c155a 100644 (file)
@@ -10,6 +10,7 @@ from concurrent.futures import _base
 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 @@ def _worker(executor_reference, work_queue):
         _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")
 
index 83184c32670537f7f94a11958e63c7266f1a9d8e..11560e65ac02c99a93eca7f203935ed015fca461 100644 (file)
@@ -11,6 +11,7 @@ test.support.import_module('threading')
 
 from test.script_helper import assert_python_ok
 
+import os
 import sys
 import threading
 import time
@@ -444,6 +445,11 @@ class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest, unittest.TestCase):
         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):
index 71ab268c7360271ec8f86147c59807fc5598b1e3..a02e8a6e657592b7cd06c728e0e602eb93aa0fff 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -129,6 +129,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #21527: Add a default number of workers to ThreadPoolExecutor equal
+  to 5 times the number of CPUs.  Patch by Claudiu Popa.
+
 - Issue #22216: smtplib now resets its state more completely after a quit.  The
   most obvious consequence of the previous behavior was a STARTTLS failure
   during a connect/starttls/quit/connect/starttls sequence.