I'm not sure from what perspective you were looking to compare asyncio to green threads (performance, readability, etc.) but there is an interesting blog post [0] by the lead architect of Twisted about the fundamental difference in programming model between explicit yielding (e.g. asyncio) and implicit yielding (e.g. green threads, regular threads). It may give you some answers.
PEP 492, from what I understood, is more about streamlining the syntax, and the major differences between asyncio (pre this proposed syntax) and green threads in terms of programming model still apply.
Glyph is a smart guy and has been doing async code for a very long time (at least in computing terms). It would be wise to consider his arguments.
I've done a project making heavy use of Python 3's asyncio feature. It is much nicer than doing the same job with threads or call-backs, in my experience. I'd welcome nicer syntax but the current functionality seems to work well.
I can't understand why someone would design a language in 2009 (Node.js) that uses callbacks. For simple programs it works but it doesn't take long to end up with an unmaintainable mess (in my experience).
The problem with "green threads" is that their context switching is unpredictable. You never know where the context is switched, potentially confusing C APIs and such.
Asyncio "threads", on the other hand, never switch context between "yield from" instructions. This makes it usable with the most bungled and complicated C APIs (e.g. Blender...), and also lets us reason more clearly about the concurrent behavior.
I'm going to go out on a limb and say this is a fallacy, you have just turned yourself (the programmer) into the context switching routine that the operating system (or python itself) does for you. IMHO computers are good (and can be made better) at scheduling and we should really avoid trying to do it ourselves manually... Getting used to thinking about where code can be context switched is IMHO worth more than shoving it under a rug and turning the programmer into the scheduler...
It's not as bad as you think it is. First thing: Asyncio doesn't force the programmer to schedule anything. The event loop does that.
Also, this kind of message-passing concurrency is not meant for cpu-intensive work, but rather for situations where there's nothing to do in a particular task much of the time. Concurrent threads/tasks in frameworks like NodeJs, Tornado and Asyncio are very good at doing nothing.
For example in a web server, a traditionally threaded "worker" spends a lot of time waiting for a connection, waiting for database requests to finish, and so on. The operating system can use that time to execute other threads. But the memory of the thread sits idle during that time.
Scheduling in asyncio is not imposed by the operating system or the programmer, and only partly by the event loop, but largely because of external circumstances like network latency/bandwith, how long do the database queries take, and how fast the user is acting.
Who writes the 'yield from' or 'async' or @coroutine (yield points, aka context switching 'places', that u have to pick correctly)...? I thought that was the programmer ;-)
Declaring in which line to switch context does not a scheduler make. Also, "yield from" does not just mean context switching but also returns a coroutine's result.
I have written quite a lot of asyncio and tornado code by now, and I can't remember a single instance where I had to yield/yield from/wait just because the computation would freeze up the thread or increase latency.
Coroutines really aren't about explicit scheduling, at the very most you can specify what code is executed without switching. And the latter is absolutely necessary in some situations. For example, threads or greenlets freak out Blender.