Skip to content
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

TLS/SSL asyncio/uvloop leaks memory #565

Open
rojamit opened this issue Sep 18, 2023 · 1 comment
Open

TLS/SSL asyncio/uvloop leaks memory #565

rojamit opened this issue Sep 18, 2023 · 1 comment

Comments

@rojamit
Copy link

rojamit commented Sep 18, 2023

python3.9 or uvloop seems to leak smaller, but python3.11 (and others?) leaks A LOT OF memory under load
test command: ab -n15000 -c15000 -r https://127.0.0.1/
(apt install apache2-utils)

import asyncio, ssl, uvloop

class HTTP(asyncio.Protocol):
    
    def __init__(self):
        self.transport = None
        
    def connection_made(self, transport) -> None:
        self.transport = transport

    def data_received(self, data) -> None:
        self.transport.write(
            b'HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n'
        )
        self.transport.close()

    def connection_lost(self, _=0) -> bool | None:
        self.transport.close()

def make_tls_context():
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ctx.load_cert_chain('cert.crt', 'cert.key')
    return ctx

tls_context = make_tls_context()
loop = uvloop.new_event_loop()
loop.set_debug(True)

async def start_server(loop):
    return await loop.create_server(
        HTTP, '127.0.0.1', 443, backlog=65535,
        ssl=tls_context)

loop.run_until_complete(start_server(loop))
loop.run_forever()
loop.close()

CPython versions tested on:
3.9, 3.11

Operating systems tested on:
Linux

@ljluestc
Copy link


import asyncio
import ssl
import uvloop

class HTTP(asyncio.Protocol):
    def __init__(self):
        self.transport = None

    def connection_made(self, transport) -> None:
        self.transport = transport

    def data_received(self, data) -> None:
        print(data)
        self.transport.write(
            b'HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n'
        )
        self.transport.close()

    def connection_lost(self, exc) -> None:
        if self.transport is not None:
            self.transport.close()
            self.transport = None

def make_tls_context():
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ctx.load_cert_chain('cert.crt', 'cert.key')  # Adjust paths to your certificates
    return ctx

async def start_server():
    loop = asyncio.get_running_loop()
    server = await loop.create_server(
        lambda: HTTP(), '127.0.0.1', 443, backlog=65535, ssl=make_tls_context()
    )
    async with server:
        await server.serve_forever()

uvloop.install()
asyncio.run(start_server())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants