<div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif">On Fri, Oct 13, 2017 at 7:38 PM, Yury Selivanov </span><span dir="ltr" style="font-family:arial,sans-serif"><<a href="mailto:yselivanov.ml@gmail.com" target="_blank">yselivanov.ml@gmail.com</a>></span><span style="font-family:arial,sans-serif"> wrote:</span><br></div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Fri, Oct 13, 2017 at 11:49 AM, Koos Zevenhoven <<a href="mailto:k7hoven@gmail.com">k7hoven@gmail.com</a>> wrote:<br>
[..]<br>
<span class="gmail-">> This was my starting point 2.5 years ago, when Yury was drafting this status<br>
> quo (PEP 492). It looked a lot of PEP 492 was inevitable, but that there<br>
> will be a problem, where each API that uses "blocking IO" somewhere under<br>
> the hood would need a duplicate version for asyncio (and one for each<br>
> third-party async framework!). I felt it was necessary to think about a<br>
> solution before PEP 492 is accepted, and this became a fairly short-lived<br>
> thread here on python-ideas:<br>
<br>
</span>Well, it's obvious why the thread was "short-lived". Don't mix<br>
non-blocking and blocking code and don't nest asyncio loops. But I<br>
believe this new subtopic is a distraction. </blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">Nesting is not the only way to have interaction between two event loops.<div class="gmail_default" style="display:inline"> But whenever anyone *does* want to nest two loops, they are perhaps more likely to be loops of different frameworks.</div></div><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">You believe that the semantics in async code is a distraction?</div></div><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif"> </span><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">You should start a new<br>
thread on Python-ideas if you want to discuss the acceptance of PEP<br>
492 2.5 years ago.<br></blockquote><div><span style="font-family:monospace,monospace"><br></span></div><div>I<div class="gmail_default" style="font-family:monospace,monospace;display:inline">'m definitely not interested in discussing the acceptance of PEP 492.</div></div><div><div class="gmail_default" style="font-family:monospace,monospace;display:inline"></div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
[..]<br>
<span class="gmail-">> The bigger question is, what should happen when a coroutine awaits on<br>
> another coroutine directly, without giving the framework a change to<br>
> interfere:<br>
><br>
><br>
> async def inner():<br>
> do_context_aware_stuff()<br>
><br>
> async def outer():<br>
> with first_context():<br>
> coro = inner()<br>
><br>
> with second_context():<br>
> await coro<br>
><br>
> The big question is: In the above, which context should the coroutine be run<br>
> in?<br>
<br>
</span>The real big question is how people usually write code. And the<br>
answer is that they *don't write it like that* at all. Many context<br>
managers in many frameworks (aiohttp, tornado, and even asyncio)<br>
require you to wrap your await expressions in them. Not coroutine<br>
instantiation.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">You know very well that I've been talking about how people usually write code etc. But we still need to handle the corner cases too.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
A more important point is that existing context solutions for async<br>
frameworks can only support a with statement around an await<br>
expression. And people that use such solutions know that 'with ...:<br>
coro = inner()' isn't going to work at all.<br>
<br>
Therefore wrapping coroutine instantiation in a 'with' statement is<br>
not a pattern. It can only become a pattern, if whatever execution<br>
context PEP accepted in Python 3.7 encouraged people to use it.<br>
<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">The code is to illustrate semantics, not an example of real code. The point is to highlight that the context has changed between when the coroutine function was called and when it is awaited. That's certainly a thing that can happen in real code, even if it is not the most typical case. I do mention this in my previous email.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
[..]<br>
<span class="gmail-">> Both of these would have their own stack of (argument, value) assignment<br>
> pairs, explained in the implementation part of the first PEP 555 draft.<br>
> While this is a complication, the performance overhead of these is so small,<br>
> that doubling the overhead should not be a performance concern.<br>
<br>
</span>Please stop handwaving performance. Using big O notation:<br>
<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">There is discussion on perfomance elsewhere, now also in this other subthread:</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default"><font face="monospace, monospace"><a href="https://mail.python.org/pipermail/python-ideas/2017-October/047327.html">https://mail.python.org/pipermail/python-ideas/2017-October/047327.html</a></font><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
PEP 555, worst complexity for uncached lookup: O(N), where 'N' is the<br>
total number of all context values for all context keys for the<br>
current frame stack. </blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">Not true. See the above link. Lookups are fast (*and* O(1), if we want them to be).</div></div><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">PEP 555 stacks are independent of frames, BTW.</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">For a recursive function you can easily have a<br>
situation where cache is invalidated often, and code starts to run<br>
slower and slower.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">Not true either. The lookups are O(1) in a recursive function, with and without nested contexts.</div><br></div><div class="gmail_default" style="font-family:monospace,monospace">I started this thread for discussion about semantics in an async context. Stefan asked about performance in the other thread, so I posted there.</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">––Koos</div><div class="gmail_default" style="font-family:monospace,monospace"></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
PEP 550 v1, worst complexity for uncached lookup: O(1), see [1].<br>
<br>
PEP 550 v2+, worst complexity for uncached lookup: O(k), where 'k' is<br>
the number of nested generators for the current frame. Usually k=1.<br>
<br>
While caching will mitigate PEP 555' bad performance characteristics<br>
in *tight loops*, the performance of uncached path must not be<br>
ignored.<br>
<br>
Yury<br>
<br>
[1] <a href="https://www.python.org/dev/peps/pep-0550/#appendix-hamt-performance-analysis" rel="noreferrer" target="_blank">https://www.python.org/dev/<wbr>peps/pep-0550/#appendix-hamt-<wbr>performance-analysis</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">+ Koos Zevenhoven + <a href="http://twitter.com/k7hoven" target="_blank">http://twitter.com/k7hoven</a> +</div>
</div></div>