]> granicus.if.org Git - python/commitdiff
asyncio: Optimize Task._wakeup
authorYury Selivanov <yselivanov@sprymix.com>
Mon, 16 Nov 2015 20:12:10 +0000 (15:12 -0500)
committerYury Selivanov <yselivanov@sprymix.com>
Mon, 16 Nov 2015 20:12:10 +0000 (15:12 -0500)
See https://github.com/python/asyncio/pull/289 for details.

Lib/asyncio/tasks.py

index 77a93e0fe0aee6d8987f887e0cfd1b880a8e107d..21940f624c5cc5e32f985b664ca04a5d86023313 100644 (file)
@@ -93,6 +93,7 @@ class Task(futures.Future):
             futures.Future.__del__(self)
 
     def _repr_info(self):
+        # Private method, do not use it.
         info = super()._repr_info()
 
         if self._must_cancel:
@@ -221,6 +222,7 @@ class Task(futures.Future):
         return True
 
     def _step(self, value=None, exc=None):
+        # Private method, do not use it.
         assert not self.done(), \
             '_step(): already done: {!r}, {!r}, {!r}'.format(self, value, exc)
         if self._must_cancel:
@@ -284,13 +286,20 @@ class Task(futures.Future):
             self = None  # Needed to break cycles when an exception occurs.
 
     def _wakeup(self, future):
+        # Private method, do not use it.
         try:
-            value = future.result()
+            future.result()
         except Exception as exc:
             # This may also be a cancellation.
             self._step(None, exc)
         else:
-            self._step(value, None)
+            # Don't pass the value of `future.result()` explicitly,
+            # as `Future.__iter__` and `Future.__await__` don't need it.
+            # If we call `_step(value, None)` instead of `_step()`,
+            # Python eval loop would use `.send(value)` method call,
+            # instead of `__next__()`, which is slower for futures
+            # that return non-generator iterators from their `__iter__`.
+            self._step()
         self = None  # Needed to break cycles when an exception occurs.