Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Support bacteria -- it's the only culture some people have!


devel / comp.lang.python / Re: [Python-ideas] yield functionality to match that of await

SubjectAuthor
o Re: [Python-ideas] yield functionality to match that of awaitChris Angelico

1
Re: [Python-ideas] yield functionality to match that of await

<mailman.84.1686610719.23016.python-list@python.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23577&group=comp.lang.python#23577

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: ros...@gmail.com (Chris Angelico)
Newsgroups: comp.lang.python
Subject: Re: [Python-ideas] yield functionality to match that of await
Date: Tue, 13 Jun 2023 08:58:25 +1000
Lines: 119
Message-ID: <mailman.84.1686610719.23016.python-list@python.org>
References: <83CACFA7-7FE8-4F58-ABAC-85767D9ED6F2@gmail.com>
<CAPTjJmq6J7GZdn2s6fGJB7GGw4qkE4tCeXsYif3CobvLhmL_yQ@mail.gmail.com>
<4E314809-5EB1-404C-989F-9E7A434053F2@gmail.com>
<CAPTjJmrS7nLnhCJe-fRpnMBKKP8TWKKOdAr3R58Z535V=sWOUQ@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Trace: news.uni-berlin.de KaGCb8VCKyEVQYft5ObPMwC2ctA/qghjo54jin1eX2vA==
Return-Path: <rosuav@gmail.com>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
reason="2048-bit key; unprotected key"
header.d=gmail.com header.i=@gmail.com header.b=Rt6KE+kr;
dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.000
X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'looks': 0.02; 'this:':
0.03; 'def': 0.04; '(for': 0.05; 'thread': 0.05; '2023': 0.07;
'architecture': 0.07; 'explanation': 0.07; 'http': 0.07; 'loop':
0.07; 'pep': 0.07; 'template': 0.07; 'thing.': 0.07; 'alone.':
0.09; 'asynchronous': 0.09; 'better,': 0.09; 'fact,': 0.09;
'memory.': 0.09; 'obviously': 0.09; 'occasionally': 0.09;
'overhead': 0.09; 'speed,': 0.09; 'spin': 0.09; 'threads': 0.09;
'versions,': 0.09; 'subject:Python': 0.12; 'coding': 0.13;
'(both': 0.16; '684': 0.16; 'behaviour': 0.16; 'benchmarking':
0.16; 'chrisa': 0.16; 'comparing': 0.16; 'constructor': 0.16;
'coroutine': 0.16; 'coroutines': 0.16; 'downside': 0.16;
'explaining': 0.16; 'extending': 0.16; 'frameworks.': 0.16;
'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16;
'functions,': 0.16; 'hardly': 0.16; 'hassle,': 0.16; 'irc': 0.16;
'long-running': 0.16; 'machine.': 0.16; 'next,': 0.16; 'opinion,':
0.16; 'refactor': 0.16; 'runtime': 0.16; 'server,': 0.16; 'sock':
0.16; 'structural': 0.16; 'subject:match': 0.16; 'subject:skip:f
10': 0.16; 'subset': 0.16; 'triggered': 0.16; 'yield': 0.16;
'wrote:': 0.16; 'python': 0.16; 'instead': 0.17; 'probably': 0.17;
"aren't": 0.19; 'calls': 0.19; 'figure': 0.19; 'implement': 0.19;
'libraries': 0.19; 'tue,': 0.19; 'to:addr:python-list': 0.20;
'option': 0.20; 'subject:: [': 0.21; 'subject:] ': 0.21;
'written': 0.22; "i've": 0.22; 'basically': 0.22; 'maybe': 0.22;
'version': 0.23; 'code': 0.23; 'run': 0.23; "i'd": 0.24;
'anything': 0.25; 'actual': 0.25; 'seems': 0.26; 'jun': 0.26;
'library': 0.26; "isn't": 0.27; 'bit': 0.27; 'function': 0.27;
'done': 0.28; 'sense': 0.28; 'thinking': 0.28; 'example,': 0.28;
'this?': 0.29; 'seem': 0.31; 'default': 0.31; 'think': 0.32;
"doesn't": 0.32; 'question': 0.32; '(this': 0.32; 'keyword': 0.32;
'language.': 0.32; 'point,': 0.32; 'to:name:python': 0.32;
'message-id:@mail.gmail.com': 0.32; 'but': 0.32; "i'm": 0.33;
'there': 0.33; 'server': 0.33; 'same': 0.34; 'header:In-Reply-
To:1': 0.34; 'now,': 0.67; 'types': 0.67; 'bad': 0.67; 'maximum':
0.67; 'more,': 0.67; 'choose': 0.67; 'per': 0.68; 'await': 0.69;
'change.': 0.69; 'compare': 0.69; 'generator': 0.69; 'lowest':
0.69; 'manually': 0.69; 'performance,': 0.69; 'stands': 0.69;
'compared': 0.71; "you'll": 0.73; 'easy': 0.74; 'read,': 0.75;
'limits': 0.76; 'poor': 0.76; 'client': 0.82; 'extra': 0.84;
'points': 0.84; 'reasons': 0.84; 'up,': 0.84; 'async/await': 0.84;
'comparable': 0.84; 'dom': 0.84; 'doubts': 0.84; 'lightweight':
0.84; 'selling': 0.84; 'transactions': 0.84; 'true:': 0.84;
'weird': 0.84; 'down,': 0.91; 'term.': 0.91; 'keywords': 0.95
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20221208; t=1686610717; x=1689202717;
h=content-transfer-encoding:to:subject:message-id:date:from
:in-reply-to:references:mime-version:from:to:cc:subject:date
:message-id:reply-to;
bh=XOPxg5on/5ws7e6mUXUs7vT/VnCqPp9WlPn9DG5B51Q=;
b=Rt6KE+kraCFQSFNSNh7gczPaSTKZWty8OQ8JUP3/1goBqLOF9ZCiIi7zPxxeankc6S
DV0HcMjP/YKLRwo+7GF5MsJxCll1lv4B3+kN0rMWfEtInN0OSb4M3IyY7yn378Kk3/aR
ErYV2hROzSxRGYTDxYzODo40Y0WbiiTUqdXwPvQuW0a0K3WF2JEodXH6P5XfQBWKRYZ1
RSttOQ3dn0p6on+z/X+SSx/NhU+JgZWU9rBzbWLX+GWrzSE29O2lNFoqk9HUs7iW3MA3
tUGAHRPXbRH3/IU9FFyqmtdyxhlOoJJ4Y/INU1rYJvp7s38uc6jVyJxWeIbhsEJteZ73
kj0A==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20221208; t=1686610717; x=1689202717;
h=content-transfer-encoding:to:subject:message-id:date:from
:in-reply-to:references:mime-version:x-gm-message-state:from:to:cc
:subject:date:message-id:reply-to;
bh=XOPxg5on/5ws7e6mUXUs7vT/VnCqPp9WlPn9DG5B51Q=;
b=ebsPTULiayREuGMQEBTjkJFHDMuKQ/nktKOom5FPJZv9/oX7DyPu0omSARZubnxaPk
IFmLCmRZ2OE6V759SDgEW8X3pU8YdJJKkGYadMzgV9IcnsJZAXGWsVQBA9s3t5a/juEP
5iBrKkhhJOzqjWWh2RQnj/WmXyxladUYmqCd4lJ5OLtyJLdscBqBnLxXM67hVhtreYaD
06z7lg422k454oJ5JoMr8+EW2VN4EXl5+PnSizK9Qc+6l8DrFND0pF0ZHep8KOfD1qxM
A+UcXq5lPvh8ncUjYBUYjdAtsGs+7hKCdbWZLSIGrG9qUA4pdiblx9ivaUt5xCCN1sOA
eJ1g==
X-Gm-Message-State: AC+VfDwe4ZH1EOo1PmMWMzHFx/b7x8LzZ5kWX9bQlwjY+EUescJa1wyK
ivHI0btNpGzaSTw3BSdGxN/u8SkOv38c0vxIptd9tTnOeEw=
X-Google-Smtp-Source: ACHHUZ6NYiMZRzynvC6pKyJjmQYh5St0LTmwULzDmBHgA7+MfakUxRUR1liAdj0v9G74xBB+AEVucaLm28Vnr+hkk3M=
X-Received: by 2002:a05:6402:2058:b0:514:9500:7e51 with SMTP id
bc24-20020a056402205800b0051495007e51mr5493261edb.9.1686610717055; Mon, 12
Jun 2023 15:58:37 -0700 (PDT)
In-Reply-To: <4E314809-5EB1-404C-989F-9E7A434053F2@gmail.com>
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: General discussion list for the Python programming language
<python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
<mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
<mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <CAPTjJmrS7nLnhCJe-fRpnMBKKP8TWKKOdAr3R58Z535V=sWOUQ@mail.gmail.com>
X-Mailman-Original-References: <83CACFA7-7FE8-4F58-ABAC-85767D9ED6F2@gmail.com>
<CAPTjJmq6J7GZdn2s6fGJB7GGw4qkE4tCeXsYif3CobvLhmL_yQ@mail.gmail.com>
<4E314809-5EB1-404C-989F-9E7A434053F2@gmail.com>
 by: Chris Angelico - Mon, 12 Jun 2023 22:58 UTC

On Tue, 13 Jun 2023 at 08:29, Dom Grigonis <dom.grigonis@gmail.com> wrote:
> > I don't know if there's a full explanation written down, but one
> > important reason is that you can refactor async functions without
> > worrying about suddenly changing their behaviour unintentionally. If
> > you happen to refactor out the last "yield" from a generator, suddenly
> > it's not a generator any more, and you'll have a weird time trying to
> > figure out what happened; but an async function is an async function
> > even if it doesn't (currently) have any await points in it.
>
> For that it would have been easier to introduce one extra keyword like `ydef` or `gdef` as opposed to a completely new subset of a language.

I think that was discussed, but the benefits were ONLY that one point,
with the downside that there'd be these confusing distinctions between
"functions defined this way" and "functions defined that way" that
only occasionally crop up. Not a good thing.

> > Another reason is that you can have asynchronous generator functions,
> > which use both await AND yield. It's not easy to create a two-layer
> > yielding system on top of yield alone.
>
> Well for that could just create a some sort of efficient standard iterator class if one wants a generator that is not triggered by coroutine loop. And set it to be the default constructor for generator comprehensions.

I suppose so, but that seems a bit awkward. And "default constructor
for generator comprehensions" isn't really a thing so I'm not sure how
that would be implemented.

> As you seem to know this topic reasonably well, hope you don’t mind me explaining the thought process I am having.
>
> I am currently just trying to choose my toolkit and I am having big doubts about asyc/await frameworks. I have done some benchmarking and `gevent` library is faster than all of them with one exception: asyncio with uvloop. Correct me if I am wrong, but the main selling point for all that hassle with coroutines is speed. If that is so, then the overhead that async/await libraries have introduced is hardly cutting. So I was just thinking if there were any reasons of not extending already existing keywords and functionality, which at least as it stands now has much lower overhead.
>
> Maybe you know any good benchmarks/materials that could provide me some sense in all this?
>

Hmm, I'd say coroutines aren't really about speed, they're about
throughput. Let's take a TCP socket server as an example (this could
be a web server, a MUD server, an IRC server, anything else). You want
a basic architecture like this:

def handle_client(sock):
while True:
line = get_line(sock) # buffered read, blah blah
if line == "quit": break
sock.send("blah blah")
sock.close()

def run_server():
mainsock = socket.socket()
mainsock.bind(...)
mainsock.listen(5)
while sock := mainsock.accept():
print("Got a connection!", sock.getpeername())
handle_client(sock)

(If I've messed something up, apologies, this is hastily whipped up
from memory. Do not use this as a template for actual socket servers,
it's probably buggy and definitely incomplete. Anyhow.)

Now, obviously this version kinda sucks. It has to handle one client
completely before going on to the next, which is utterly terrible for
a long-running protocol like TELNET, and pretty poor even for HTTP
0.9. So what are the options for concurrency?

1) Spawn a subprocess for every client. Maximum overhead, maximum isolation..
2) Spin off a new thread for every client. Much much less overhead but
still notable.
3) Run an event loop using select.select() or equivalent, managing
everything manually.
4) Use an asyncio event loop.

Individual processes scales abysmally, although occasionally the
isolation is of value (FTP servers come to mind). Threads is a lot
better, and I've run plenty of threaded servers in the past, but
you'll run into thread limits before you run into socket limits, so at
some point, threads will restrict your throughput.

A lightweight event loop is by far the lowest overhead. This MIGHT be
measured as higher performance, but it's usually more visible in
throughput (for example, "100 transactions per second" vs "1000
transactions per second"). However, doing this manually can be a bit
of a pain, as you basically have to implement your own state machine.
Not too bad for some types of server, but annoying for anything that's
at all stateful.

So that's where asyncio comes in. It's approximately the same runtime
overhead as an event loop, but with way WAY less coding overhead. In
fact, the code looks basically the same as threaded or forking code -
you just say "here, go run this thing in a separate task" instead of
juggling all the separate state machines.

"All that hassle" is, of course, a relative term. So my first question
is: what are you comparing against? If you're comparing against
running your own select.select() loop, it's way *less* hassle, but
compared to using threads, I'd say it's pretty comparable - definitely
some additional hassle (since you have to use nonblocking calls
everywhere), but ideally, not too much structural change.

In my opinion, asyncio is best compared against threads, although with
upcoming Python versions, there may be an additional option to compare
against, which is threads that run separate subinterpreters (see PEP
554 and PEP 684 for details). In the ideal situation (both PEPs
accepted and implemented, and each client getting a thread with a
dedicated subinterpreter), this could sit nicely between threads and
processes, giving an in-between level of isolation, performance,
overhead, and throughput.

ChrisA

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor