Skip to content

asyncio: do not create unneeded lambdas #108903

Closed
@sobolevn

Description

@sobolevn

Bug report

There are multiple places in asyncio code and docs where this pattern is used: lambda: some_call()

While this pattern can be used in some rare cases, generally it is not a good thing to have for several reasons:

  1. It creates an extra frame for no reason
  2. It spends more bytecode entries to do the same thing
>>> import dis
>>> def a():
...     return lambda: str()
... 
>>> def b():
...      return str
... 

>>> dis.dis(a)
  1           0 RESUME                   0

  2           2 LOAD_CONST               1 (<code object <lambda> at 0x10136d040, file "<stdin>", line 2>)
              4 MAKE_FUNCTION
              6 RETURN_VALUE

Disassembly of <code object <lambda> at 0x10136d040, file "<stdin>", line 2>:
  2           0 RESUME                   0
              2 LOAD_GLOBAL              1 (str + NULL)
             12 CALL                     0
             20 RETURN_VALUE

>>> dis.dis(b)
  1           0 RESUME                   0

  2           2 LOAD_GLOBAL              0 (str)
             12 RETURN_VALUE

I propose to remove this pattern from asyncio, because it is designed to be load-intensive and such micro-optimizations surely help.

diff --git Doc/library/asyncio-protocol.rst Doc/library/asyncio-protocol.rst
index 7bc906eaafc..9781bda8b27 100644
--- Doc/library/asyncio-protocol.rst
+++ Doc/library/asyncio-protocol.rst
@@ -746,7 +746,7 @@ received data, and close the connection::
         loop = asyncio.get_running_loop()
 
         server = await loop.create_server(
-            lambda: EchoServerProtocol(),
+            EchoServerProtocol,
             '127.0.0.1', 8888)
 
         async with server:
@@ -850,7 +850,7 @@ method, sends back received data::
         # One protocol instance will be created to serve all
         # client requests.
         transport, protocol = await loop.create_datagram_endpoint(
-            lambda: EchoServerProtocol(),
+            EchoServerProtocol,
             local_addr=('127.0.0.1', 9999))
 
         try:
diff --git Lib/asyncio/sslproto.py Lib/asyncio/sslproto.py
index 488e17d8bcc..3eb65a8a08b 100644
--- Lib/asyncio/sslproto.py
+++ Lib/asyncio/sslproto.py
@@ -539,7 +539,7 @@ def _start_handshake(self):
         # start handshake timeout count down
         self._handshake_timeout_handle = \
             self._loop.call_later(self._ssl_handshake_timeout,
-                                  lambda: self._check_handshake_timeout())
+                                  self._check_handshake_timeout)
 
         self._do_handshake()
 
@@ -619,7 +619,7 @@ def _start_shutdown(self):
             self._set_state(SSLProtocolState.FLUSHING)
             self._shutdown_timeout_handle = self._loop.call_later(
                 self._ssl_shutdown_timeout,
-                lambda: self._check_shutdown_timeout()
+                self._check_shutdown_timeout
             )
             self._do_flush()
 
@@ -758,7 +758,7 @@ def _do_read__buffered(self):
                     else:
                         break
                 else:
-                    self._loop.call_soon(lambda: self._do_read())
+                    self._loop.call_soon(self._do_read)
         except SSLAgainErrors:
             pass
         if offset > 0:

I will send a PR.

Linked PRs

Metadata

Metadata

Assignees

Labels

stdlibPython modules in the Lib dirtopic-asynciotype-bugAn unexpected behavior, bug, or error

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions