)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"19559799fdfddaa5c498dd91e7b765acf5e43a92","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Victor Stinner \u003cvictor.stinner@enovance.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-02-05 18:06:48 +0100"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Reeplace eventlet with asyncio"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"First draft."},{"line_number":10,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"da86d52c_3e230fbe","line":7,"updated":"2015-02-05 17:27:42.000000000","message":"Oops, typo: r*e*place","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"}],"specs/asyncio.rst":[{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5d33a77f39132079be9b01cc9e55d8254cf0b1a2","unresolved":false,"context_lines":[{"line_number":9,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Replacing eventlet with asyncio should reduce the number of race condition bugs"},{"line_number":12,"context_line":"and may improve overall OpenStack performances."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_88f72af5","line":12,"updated":"2015-02-06 21:51:37.000000000","message":"I thought a big part of this was python 3 support.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":9,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Replacing eventlet with asyncio should reduce the number of race condition bugs"},{"line_number":12,"context_line":"and may improve overall OpenStack performances."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_dced3ff1","line":12,"in_reply_to":"da86d52c_88f72af5","updated":"2015-02-09 17:05:25.000000000","message":"I\u0027m working on porting OpenStack to Python 3 (*), but I prefer to not discuss asyncio and Python 3 in the same thread. It\u0027s not possible to use directly OpenStack with Python 3, because most OpenStack applications don\u0027t support Python 3 and some companies will probably \"have to\" keep Python 2. Doug Hellmann told me that he may write a spec to discuss Python 3, and maybe propose to drop Python 2 support (!).\n\nI don\u0027t think that switching from Python 2 to Python 3 will give a huge speedup. Replacing blocking code with concurrent asynchronous code can give a real speedup (see benchmark below).\n\n(*) https://wiki.openstack.org/wiki/Python3","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5d33a77f39132079be9b01cc9e55d8254cf0b1a2","unresolved":false,"context_lines":[{"line_number":25,"context_line":"eventlet which also became the defacto standard in OpenStack."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"This specification proposes to replace eventlet, implicit async programming,"},{"line_number":28,"context_line":"with asyncio, explicit async programming. It should fix eventlet issues,"},{"line_number":29,"context_line":"prepare OpenStack for the future (asyncio is now part of the Python language)"},{"line_number":30,"context_line":"and may improve overall OpenStack performances."},{"line_number":31,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_554eaf97","line":28,"range":{"start_line":28,"start_character":65,"end_line":28,"end_character":71},"updated":"2015-02-06 21:51:37.000000000","message":"can you elaborate","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":25,"context_line":"eventlet which also became the defacto standard in OpenStack."},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"This specification proposes to replace eventlet, implicit async programming,"},{"line_number":28,"context_line":"with asyncio, explicit async programming. It should fix eventlet issues,"},{"line_number":29,"context_line":"prepare OpenStack for the future (asyncio is now part of the Python language)"},{"line_number":30,"context_line":"and may improve overall OpenStack performances."},{"line_number":31,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_12ddfb42","line":28,"in_reply_to":"da86d52c_554eaf97","updated":"2015-02-09 17:05:25.000000000","message":"See eventlet drawbacks below.\n\nThe main eventlet issue is that you have to write carefully your code to handle concurrency anywhere. Much lesser code need to be protected with explicit asynchronous programming.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"698e2a3136f82cc4651b20d7f027c6dcebb27792","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"* Explicit asynchronous programming reduces the risk of race conditions: the"},{"line_number":41,"context_line":"  developer can identify easily where a function (coroutine) can be"},{"line_number":42,"context_line":"  interrupted."},{"line_number":43,"context_line":"* asyncio is maintained by the Python project and rely on existing modules of"},{"line_number":44,"context_line":"  the standard library like select, selectors or concurrent.futures. No"},{"line_number":45,"context_line":"  need for assembler code (as greenlet)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_3c03e077","line":42,"updated":"2015-02-07 00:50:34.000000000","message":"This is a very bold and debateable assertion.  I don\u0027t think it can be accepted without demonstrations of blocks of code in current Openstack applications that illustrate existing race conditions which can only be solved through asynchronous programming.   \n\nExplicit async programming cannot affect the vast majority of real-world race conditions, which are those which occur between applications and against databases and other services.    Database races and deadlocks will continue to occur regardless of programming pattern in use; it is simple to deadlock a database without any concurrency scheme at all, just lock rows A and B in two transactions which are mutually dependent on each other.    \n\nThe kinds of errors that async can theoretically help with are those that would occur when writing code that is sharing data between threads within one process; however, many Openstack applciations are simple WSGI applications, and while they may run within threads, do not share data in-process between those threads.  There are no issues in such applications for async to solve.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"* Explicit asynchronous programming reduces the risk of race conditions: the"},{"line_number":41,"context_line":"  developer can identify easily where a function (coroutine) can be"},{"line_number":42,"context_line":"  interrupted."},{"line_number":43,"context_line":"* asyncio is maintained by the Python project and rely on existing modules of"},{"line_number":44,"context_line":"  the standard library like select, selectors or concurrent.futures. No"},{"line_number":45,"context_line":"  need for assembler code (as greenlet)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_f5a5b1b5","line":42,"in_reply_to":"da86d52c_3c03e077","updated":"2015-02-09 17:05:25.000000000","message":"I didn\u0027t write that eventlet issues cannot be fixed. It\u0027s also possible to write bugs (including race conditions) with asyncio. It is possible to write safe code with eventlet, it\u0027s just harder. That\u0027s why I wrote \"reduces the risk\".\n\nRead the \"Ca(sh|che Coherent) Money\" section of the https://glyph.twistedmatrix.com/2014/02/unyielding.html article: it explains better than me how a simple log (call to a log() function) can introduce a subtle race conditions. It explains how explicit asychronous programming reduces the risk of introducing bugs. With eventlet, if log() becomes asynchronous, you have no reminder that you have to take care of race conditions during a review of the change. With asyncio, you must add \"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your code becomes asynchronous.\"","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"276685e204148e4450623144efde2e6326f67603","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"* Explicit asynchronous programming reduces the risk of race conditions: the"},{"line_number":41,"context_line":"  developer can identify easily where a function (coroutine) can be"},{"line_number":42,"context_line":"  interrupted."},{"line_number":43,"context_line":"* asyncio is maintained by the Python project and rely on existing modules of"},{"line_number":44,"context_line":"  the standard library like select, selectors or concurrent.futures. No"},{"line_number":45,"context_line":"  need for assembler code (as greenlet)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_f17140df","line":42,"in_reply_to":"da86d52c_f5a5b1b5","updated":"2015-02-09 18:15:45.000000000","message":"Yeah I pretty much disagree with Glyph\u0027s post and so do a lot of other people, see https://news.ycombinator.com/item?id\u003d8990850 for a sample.   Threads are used virtually everywhere in software, for decades.  They aren\u0027t perfect but they are certainly not as awful as Glyph describes.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5d33a77f39132079be9b01cc9e55d8254cf0b1a2","unresolved":false,"context_lines":[{"line_number":51,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_b5236bbd","line":54,"updated":"2015-02-06 21:51:37.000000000","message":"these sound like two really big risks. Trading one set of issues for another unknown set.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":51,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_bc76cb04","line":54,"in_reply_to":"da86d52c_06332bf7","updated":"2015-02-09 17:05:25.000000000","message":"I\u0027m working directly on asyncio. I fixed \"all\" known issues. There is one remaining open issue on asyncio.Condition but I never used it and I don\u0027t like the proposed fix:\nhttp://bugs.python.org/issue22970\n(it\u0027s on my TODO list)\n\nAlmost all remaining issues are feature requests. Other issues are reminders and requests to review existing code to validate it.\n\nDid you take a look at the list of open eventlet issues recently? I don\u0027t so I cannot compare it to asyncio.\nhttps://github.com/eventlet/eventlet/issues\n\nI\u0027m still waiting for a review on my latest eventlet pull request:\nhttps://github.com/eventlet/eventlet/pull/187\n\nTo see asyncio issues at bugs.python.org, it\u0027s better to filter by component (asyncio):\nhttp://bugs.python.org/issue?@columns\u003dtitle,id,activity,status\u0026@sort\u003d-activity\u0026@filter\u003dstatus,components\u0026@pagesize\u003d50\u0026@startwith\u003d0\u0026status\u003d1\u0026components\u003d30\u0026@dispname\u003dasyncio\n\nAt bugs.python.org, there are 20 open \"issues\", but also 69 closed issues. At code.google.com, there are 27 open \"issues\", but also 193 closed issues ;-)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"4fc34a8614de7021b2176f2cef120dc9ea63662d","unresolved":false,"context_lines":[{"line_number":51,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_845ef3e7","line":54,"in_reply_to":"da86d52c_9a357948","updated":"2015-02-09 22:58:40.000000000","message":"The spec proposes to use trollius which is a third party module. I maintain the module and I release it more often than asyncio, when a major bug is fixed (or a new cool feature is added, yeah, it also occurs!) for example.\n\nTrollius changelog:\nhttp://trollius.readthedocs.org/changelog.html","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":51,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_06332bf7","line":54,"in_reply_to":"da86d52c_b5236bbd","updated":"2015-02-06 23:33:54.000000000","message":"I\u0027m gonna have to agree.\n\nSeeing http://tinyurl.com/nxqjp4l  (open asyncio issues) with  http://tinyurl.com/k7z5rpg (closed either fixed, or invalid? ones) makes me wonder if this is ready just yet....\n\nMy gut sorta thinks it needs to bake more. Now maybe my gut is wrong idk...","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":51,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_9a357948","line":54,"in_reply_to":"da86d52c_bc76cb04","updated":"2015-02-09 18:47:20.000000000","message":"Agreed, I know u fixed a lot of them, but that means they aren\u0027t yet going to appear until python 3.5+(?) so that means what for most the openstack folks that run 2.7? I know eventlet probably isn\u0027t much better (and is equally if not more slow accepting pull requests), but maybe this goes back to that talk of just using threads...","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"698e2a3136f82cc4651b20d7f027c6dcebb27792","unresolved":false,"context_lines":[{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_57d4ef46","line":55,"updated":"2015-02-07 00:50:34.000000000","message":"additional drawbacks that should be worked in:\n\n1. there are no Python database APIs (DBAPI) that can potentially support asyncio, other than psycopg2; the only solution for all other DBAPIs is to throw them into a thread pool, thereby eliminating any advantage of being able to control when IO will happen in those cases.\n\n2. database programming involves the production of many IO calls to a backend server within a single transaction; explicit async adds a vast amount of entirely predictable and useless boilerplate, making the code harder to write, read, debug, and follow.\n\n3. async programming is \"viral\" - it\u0027s not possible to use async programming in one small part of an application without all libraries used by that part also being converted to be \"async\".\n\n4. async programming produces Python code that is fundamentally slower.  A single function or method is now broken up among many \"yield froms\" which add up to much more Python latency, and additionally for return values to be preserved, relies upon a StopIteration exception throw; exception throws in Python are extremely slow.  The example at http://paste.openstack.org/show/168385/ illustrates that the most minimal latency added by a single \"yield from\" call, which is unnecessary if async IO isn\u0027t used, causes a one line function that attempts to return the value \"5\" to run 1000% slower in a speed test.   Within database-centric code, this latency would be multiplied throughout thousands of functions that all will be forced to propagate \"yield froms\" for all database operations. \n\n5. Database access libraries are made much more complex by async patterns, and traditional ORM patterns like lazy loading are made impossible.  All Openstack code that deals with databases would be made necessarily much more complex, verbose, and slow, if explicit async is a requirement.\n\n6. SQLAlchemy has no support for async and would either need to be largely re-engineered or replaced.  A re-engineering of SQLA to work around asyncIO would necessarily be within a Python 3.4-only port, and would perform dramatically slower for the Python overhead reasons mentioned previously.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_a5205e9c","line":55,"in_reply_to":"da86d52c_1106d420","updated":"2015-02-09 18:47:20.000000000","message":"I\u0027d also like the \u0027py2/py3 compat at http://trollius.readthedocs.org/asyncio.html#write-code-working-on-trollius-and-tulip\u0027 to be much more explanatory, getting into the nitty-gritty on how this works. It\u0027d be nice to have examples (side-by-side?) of how to make this work and common patterns u have seen... Maybe in-depth details (or an example library having both trollious and asyncio) would be helpful for folks.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_e24c1a79","line":55,"in_reply_to":"da86d52c_57d4ef46","updated":"2015-02-09 17:05:25.000000000","message":"\u003e 1. there are no Python database APIs (DBAPI) that can potentially support asyncio, other than psycopg2\n\nI give a list below. There are asyncio compatible drivers for MySQL, PostgreSQL, MongoDB, memcached, redis.\n\nDo you need more drivers for OpenStack?\n\n\u003e (1) the only solution for all other DBAPIs is to throw them into a thread pool, thereby eliminating any advantage of being able to control when IO will happen in those cases.\n\nWe can also write missing drivers.\n\n\u003e 4. async programming produces Python code that is fundamentally slower (...)\n\nYour micro-benchmark is irrevelant. A DB query is much slower than calling a single Python function or consuming a Python generator. You should write a benchmark fetching data from a DB to get more realistic numbers. See also the  API Hour benchmark mentionned below.\n\nYes: adding \"yield from\" makes the code slower. But usually, most time is spent to wait for \"I/O\" (external data).\n\n\u003e 5. Database access libraries are made much more complex by async patterns, and traditional ORM patterns like lazy loading are made impossible.\n\nTo use, it\u0027s not more complex, just add some \"yield from\". Example with aiopg:\nhttp://aiopg.readthedocs.org/en/stable/core.html#connection\n\nDo you mean to implement the access library?\n\nI don\u0027t see why asyncio cannot be lazy. Pseudo-code:\n\ndef lazy_fetch(self):\n    if self._data is None:\n        self._data \u003d yield from self.fetch()\n    return self._data\n\nIf data is already fetched, the generator directly returns the result. Use it like that:\n\ndata \u003d yield from conn.lazy_fetch()\n\n\u003e 6. SQLAlchemy has no support for async and would either need to be largely re-engineered or replaced.\n\nI don\u0027t think that SQLA should be dropped, it would be a waste of time to replace it with something else. We should \"just\" add an additional asynchronous API. So the user can choose between a blocking or an asynchronous client.\n\nBy the way, there is already a partial port of SQLAchemy to asyncio in aiopg:\nhttps://github.com/aio-libs/aiopg/tree/master/aiopg/sa\n\nI don\u0027t know the status of this SQLAchemy \"port\".","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"6f119e8d0b6d7f023a01b1c290608b87797ba639","unresolved":false,"context_lines":[{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_d71b7f1a","line":55,"in_reply_to":"da86d52c_57d4ef46","updated":"2015-02-07 00:54:35.000000000","message":"oops, 600% slower, not 1000%.  Sorry.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"276685e204148e4450623144efde2e6326f67603","unresolved":false,"context_lines":[{"line_number":52,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":53,"context_line":"  project is actively developed and its community is active."},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"Proposed change"},{"line_number":57,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_1106d420","line":55,"in_reply_to":"da86d52c_e24c1a79","updated":"2015-02-09 18:15:45.000000000","message":"\u003e  There are asyncio compatible drivers for MySQL,\n\nthat\u0027s great news.    Can you please add it to https://wiki.openstack.org/wiki/PyMySQL_evaluation?   A handful of us have worked on this post and none of us are aware of such a driver.   Note that a driver that throws itself into a threadpool doesn\u0027t count.  SQLAlchemy\u0027s eventual implementation will do this for people just like all the other libraries do.\n\n\u003e We can also write missing drivers.\n\nOK....that is... a *very big deal*!   That should be part of this proposal.\n\n\u003e Yes: adding \"yield from\" makes the code slower. But usually, most time is spent to wait for \"I/O\" (external data).\n\nThis is wrong in two ways.\n\nFirst, the latency added to function calls is *always* significant, everywhere.    As I\u0027ve said, I spend many hours every few months trying to reduce function call overhead, staring for hours at runsnake profiles, trimming down everything I possible can, from everywhere.  All of it makes a difference.   See http://techspot.zzzeek.org/2010/12/12/a-tale-of-three-profiles/ for a sample of what this is like.  That post is five years old.  The work there continues all the time.   \n\nAlso, the time spent waiting for IO is actually *not at all* the slowest part in Python!   It\u0027s easy to find people lamenting how unbelievably slow Python is compared to C code, how much overhead a library like SQLAlchemy (or any database abstraction) adds:\n\n\"Why is SQLAlchemy insert with sqlite 25 times slower than using sqlite3 directly?\" http://stackoverflow.com/questions/11769366/why-is-sqlalchemy-insert-with-sqlite-25-times-slower-than-using-sqlite3-directly/11769768#11769768\n\n\"Why is loading SQLAlchemy objects via the ORM 5-8x slower than rows via a raw MySQLdb cursor?\" http://stackoverflow.com/questions/23185319/why-is-loading-sqlalchemy-objects-via-the-orm-5-8x-slower-than-rows-via-a-raw-my/25534166#25534166\n\nLest you think this is just SQLAlchemy\u0027s problem, it\u0027s not.\nRead also at https://wiki.openstack.org/wiki/PyMySQL_evaluation#Architecture_and_Performance where I discuss just how blazingly fast MySQLdb, written in C, is compared to PyMySQL and MySQL-connector.  PyMySQL and MySQL-connector complete the sample script in 10-15 seconds; MySQLdb, in 1 second.  This is all Python overhead. With the vast majority of database queries (eg. queries that are only 50ms or less typically), IO is *nothing*.   It\u0027s difficult to get a Python script to really be IO-bound with relational databases unless you\u0027re running big analytic queries, which we\u0027re not.\n\n\u003e I don\u0027t see why asyncio cannot be lazy. Pseudo-code:\n\nOk this is what we mean by lazy loading:\n\n    user \u003d session.query(User).get(1)\n    print (user.addresses)   # \u003c-- runs a query\n\nSo we mean implicit lazy loading.   All ORMs do this.\n\nNow, for async SQLAlchemy, I\u0027m obviously planning on having to throw this away.  Users who want to use the ORM with async IO will have to say:\n\n    user \u003d yield from session.query(User).get(1)\n    yield from populate(user.addresses)\n\ni know the async crowd is OK with that.  So they\u0027ll get it!  But in the real world of DB programming, where fetching additional bits of DB data is continuously needed, the above is totally verbose and inconvenient, but really this is only an extension of the fact that littering code with \"yield from\" everywhere is already verbose and inconvenient.    That is to say, the DB access function I need to write with asyncio is basically *identical* to the function I\u0027d write in traditional code, except it requires \"yield from\" in the correct spaces.  Code that needs to be explicitly present and is entirely predictable is the definition of boilerplate.   \n\n\n\u003e I don\u0027t think that SQLA should be dropped, it would be a waste of time to replace it with something else. We should \"just\" add an additional asynchronous API. So the user can choose between a blocking or an asynchronous client.\n\nYes, it is totally in SQLAlchemy\u0027s interests to not bet on a winner here, and the very fortunate thing is that asyncio\u0027s allowance of \"yield from\", maintaining at least the appearance of return values, and probably most importantly preserving exception catch structures makes it vastly easier to produce this layer than when I looked at Twisted.    SQLAlchemy 1.0 needs to be released but then working on the async layer will likely be a key area for 1.1, not because i necessarily endorse it for most cases,  but at least once I write it, then I can just let people do what they want :).   asyncio is of course *fun* to use, there\u0027s that satisfaction one gets when they get their head around those patterns, which IMO is a central reason systems like node.js and tornado are popular. \n\nI am still concerned over the trollius incompatibility, however.   The answers trollius has for how to create code that is py2/py3 compat at http://trollius.readthedocs.org/asyncio.html#write-code-working-on-trollius-and-tulip are IMO not sufficient.   Given that Python 3 has definitely improved the performance of a \"catch StopIteration\" I\u0027d prefer if the switch to Python 3 could happen first, before the switch to asyncio.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":62,"context_line":"Prepare OpenStack (Oslo Messaging) to support trollius coroutines using"},{"line_number":63,"context_line":"``yield``: explicit asynchronous programming. Eventlet is still supported,"},{"line_number":64,"context_line":"used by default, and applications and libraries don\u0027t need to be modified at"},{"line_number":65,"context_line":"this point."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"Already done:"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_467363b4","line":65,"updated":"2015-02-06 23:33:54.000000000","message":"Seems like a good starting point (and one that I know has been under progress).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5f73154e9b751aaf29c8ba2913bd2bdf87daee7b","unresolved":false,"context_lines":[{"line_number":62,"context_line":"Prepare OpenStack (Oslo Messaging) to support trollius coroutines using"},{"line_number":63,"context_line":"``yield``: explicit asynchronous programming. Eventlet is still supported,"},{"line_number":64,"context_line":"used by default, and applications and libraries don\u0027t need to be modified at"},{"line_number":65,"context_line":"this point."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"Already done:"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_73a8e2db","line":65,"in_reply_to":"da86d52c_467363b4","updated":"2015-02-10 01:18:58.000000000","message":"Yeah, this would be a nice way to help shake out further issues. Making trollius work with oslo.messaging without requiring other changes.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5d33a77f39132079be9b01cc9e55d8254cf0b1a2","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"* Add aioeventlet dependency to OpenStack"},{"line_number":78,"context_line":"* Write an aioeventlet executor for Oslo Messaging: code written, change"},{"line_number":79,"context_line":"  approved, but not merged yet (need aioeventlet dependency)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"Second part (to do): rewrite code as trollius coroutines"},{"line_number":82,"context_line":"--------------------------------------------------------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_08b5fa30","line":79,"updated":"2015-02-06 21:51:37.000000000","message":"How well tested is trollius?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"* Add aioeventlet dependency to OpenStack"},{"line_number":78,"context_line":"* Write an aioeventlet executor for Oslo Messaging: code written, change"},{"line_number":79,"context_line":"  approved, but not merged yet (need aioeventlet dependency)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"Second part (to do): rewrite code as trollius coroutines"},{"line_number":82,"context_line":"--------------------------------------------------------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_fc083e93","line":79,"in_reply_to":"da86d52c_08b5fa30","updated":"2015-02-09 17:05:25.000000000","message":"As well as asyncio: trollius is a fork, it shares almost all the code with asyncio. The asyncio/trollius test suite has 883 tests (+ 16 tests from aiotest).\n\nFYI I\u0027m running trollius test suite on Linux and Windows, and sometimes on FreeBSD and OpenBSD. asyncio is tested by a CI on even more platforms (see Python buildbots).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1849,"name":"Joe Gordon","email":"joe.gordon0@gmail.com","username":"jogo"},"change_message_id":"5f73154e9b751aaf29c8ba2913bd2bdf87daee7b","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"* Add aioeventlet dependency to OpenStack"},{"line_number":78,"context_line":"* Write an aioeventlet executor for Oslo Messaging: code written, change"},{"line_number":79,"context_line":"  approved, but not merged yet (need aioeventlet dependency)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"Second part (to do): rewrite code as trollius coroutines"},{"line_number":82,"context_line":"--------------------------------------------------------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_13824652","line":79,"in_reply_to":"da86d52c_fc083e93","updated":"2015-02-10 01:18:58.000000000","message":"has it been used in \u0027production\u0027 (whatever that means).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":89,"context_line":"The first application candidate is Ceilometer. The Ceilometer project is young,"},{"line_number":90,"context_line":"developers are aware of eventlet issues and like Python 3, and Ceilometer don\u0027t"},{"line_number":91,"context_line":"rely so much on asynchronous programming: most time is spent into waiting the"},{"line_number":92,"context_line":"database anyway."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"The goal is to port Ceilometer to explicit asynchronous programming during the"},{"line_number":95,"context_line":"cycle of OpenStack Kilo."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_a6a97fe1","line":92,"updated":"2015-02-06 23:33:54.000000000","message":"What database library do u plan on using that supports asyncio programming (afaik it won\u0027t be sqlalchemy). So integrating projects that move this way will need to re-do there entire db layer (which is pretty tightly coupled in most of the projects with the rest of the code); that seems like a huge effort on its own.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":89,"context_line":"The first application candidate is Ceilometer. The Ceilometer project is young,"},{"line_number":90,"context_line":"developers are aware of eventlet issues and like Python 3, and Ceilometer don\u0027t"},{"line_number":91,"context_line":"rely so much on asynchronous programming: most time is spent into waiting the"},{"line_number":92,"context_line":"database anyway."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"The goal is to port Ceilometer to explicit asynchronous programming during the"},{"line_number":95,"context_line":"cycle of OpenStack Kilo."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_7c69ae24","line":92,"in_reply_to":"da86d52c_a6a97fe1","updated":"2015-02-09 17:05:25.000000000","message":"The spec targets Ceilometer. For Ceilometer, it should be ok to add a new storage implementation which supports asyncio. Or maybe add support for asyncio in an existing implementation like storage/impl_mongodb.py.\n\nIt would be nice to make asyncio optional in Ceilometer. I don\u0027t know yet if it is possible. So it will easier to compare performances, identify regressions, etc. Later the eventlet code would be dropped if asyncio code is well accepted and doesn\u0027t introduce new issues.\n\nFor OpenStack in general, it would be nice to enhance SQLAchemy. I don\u0027t see why SQLA couldn\u0027t support asyncio.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"fef8e02583579a926bdc83aea0bf3cde5b9ce99b","unresolved":false,"context_lines":[{"line_number":92,"context_line":"database anyway."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"The goal is to port Ceilometer to explicit asynchronous programming during the"},{"line_number":95,"context_line":"cycle of OpenStack Kilo."},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Some applications may continue to use implicit asynchronous programming. For"},{"line_number":98,"context_line":"example, nova is probably the most complex part beacuse it is and old project"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_314886b2","line":95,"updated":"2015-02-06 10:47:22.000000000","message":"Kilo or L?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"05907a80882516cbde3f137e83fe07bc710d0c2f","unresolved":false,"context_lines":[{"line_number":92,"context_line":"database anyway."},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"The goal is to port Ceilometer to explicit asynchronous programming during the"},{"line_number":95,"context_line":"cycle of OpenStack Kilo."},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Some applications may continue to use implicit asynchronous programming. For"},{"line_number":98,"context_line":"example, nova is probably the most complex part beacuse it is and old project"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_df101150","line":95,"in_reply_to":"da86d52c_314886b2","updated":"2015-02-06 11:34:19.000000000","message":"Oh, I copy/pasted this sentence from and \"old\" plan. We are very close to have the first part done in Kilo, but the second part is too late for Kilo. The L release is a more realist plan!\n\nThe last part is a long term plan, I prefer to even not estimate it right now :-)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":106,"context_line":"* Redesign the service class of Oslo Incubator to support aioeventlet and/or"},{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_46e8c316","line":109,"updated":"2015-02-06 23:33:54.000000000","message":"Is asyncio/trollius ready for this?\n\nWouldn\u0027t http://bugs.python.org/issue22087 need to be fixed for this (to enable forking correctly?). Or at least be fork capable? Is it ready for that?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":106,"context_line":"* Redesign the service class of Oslo Incubator to support aioeventlet and/or"},{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_7c736ee7","line":109,"in_reply_to":"da86d52c_46e8c316","updated":"2015-02-09 17:05:25.000000000","message":"Even if asyncio might support fork (which would be a new feature), the current design of the Service class is just broken. Instanciate an application and then fork is just wrong and lead to various kind of issues.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":106,"context_line":"* Redesign the service class of Oslo Incubator to support aioeventlet and/or"},{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_85bfda5f","line":109,"in_reply_to":"da86d52c_7c736ee7","updated":"2015-02-09 18:47:20.000000000","message":"Sure, but doesn\u0027t asyncio need to support fork for u to replace the service.py class/module (even if the class/module is not so good).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"4fc34a8614de7021b2176f2cef120dc9ea63662d","unresolved":false,"context_lines":[{"line_number":106,"context_line":"* Redesign the service class of Oslo Incubator to support aioeventlet and/or"},{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_7fd34a38","line":109,"in_reply_to":"da86d52c_85bfda5f","updated":"2015-02-09 22:58:40.000000000","message":"IMO you must fork before running your application, not the opposite. So there is not need to support fork. And this is also true for eventlet.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."},{"line_number":113,"context_line":"* Rewrite Ceilometer endpoints (RPC methods) as trollius coroutines."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_a645ff18","line":110,"updated":"2015-02-06 23:33:54.000000000","message":"What \u0027OpenStack depedencencies\u0027 are u thinking of here because that could be multiple projects (each taking quite a while just to get written using explicit asynchronous programming)?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":107,"context_line":"  trollius.  Currently, the class is designed for eventlet. The service class"},{"line_number":108,"context_line":"  is instanciated before forking, which requires hacks on eventlet to update"},{"line_number":109,"context_line":"  file descriptors."},{"line_number":110,"context_line":"* In Ceilometer and its OpenStack depedencencies: add new functions which"},{"line_number":111,"context_line":"  are written with explicit asynchronous programming in mind (ex: trollius"},{"line_number":112,"context_line":"  coroutines written with ``yield``)."},{"line_number":113,"context_line":"* Rewrite Ceilometer endpoints (RPC methods) as trollius coroutines."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_dffe0c05","line":110,"in_reply_to":"da86d52c_a645ff18","updated":"2015-02-09 17:05:25.000000000","message":"We don\u0027t have to port all code to asyncio at once. loop.run_in_executor() workaround should be enough in most cases. It\u0027s also possible to call blocking code in asyncio, it\u0027s just less efficient. So it depends on the expected performances.\n\nI\u0027m interested to port a library to asyncio if it makes sense to get more performances. In general, I/O operations should be done asynchrously for best performances (to handle more clients concurrently). DB and HTTP queries for example. Oslo Messaging should be support asyncio: not only to write an endpoint (the patch was just merged), but also to call a RPC.\n\nSorry, today I don\u0027t know Ceilometer and OpenStack well enough to list dependencies which are interesting to be ported.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"efdab6de0bbd6f772aae789d6c6d17a8ff8e1c52","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Questions:"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"* Putting a blocking call to ``loop.run_forever()`` may need to redesign"},{"line_number":154,"context_line":"  Ceilometer, this part is unclear to me right now."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"Optimization, can be done later:"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_9724a7b0","line":154,"updated":"2015-02-07 00:35:23.000000000","message":"What means \u0027redesign Ceilometer\u0027 :-/\n\nLike a full redesign, something tiny, something medium?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Questions:"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"* Putting a blocking call to ``loop.run_forever()`` may need to redesign"},{"line_number":154,"context_line":"  Ceilometer, this part is unclear to me right now."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"Optimization, can be done later:"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_9f5494cb","line":154,"in_reply_to":"da86d52c_9724a7b0","updated":"2015-02-09 17:05:25.000000000","message":"I\u0027m talking about the \"main()\" function. In fact, it\u0027s again the evil Service class. The \"main()\" function is the setuptools endpoint. For example, ceilometer.cli.collector_service() for ceilometer-collector:\n\ndef collector_service():\n    service.prepare_service()\n    launcher \u003d os_service.ProcessLauncher()\n    launcher.launch_service(\n        collector.CollectorService(),\n        workers\u003dservice.get_workers(\u0027collector\u0027))\n    launcher.wait()\n\nlauncher.wait() should call loop.run_forever().","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Questions:"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"* Putting a blocking call to ``loop.run_forever()`` may need to redesign"},{"line_number":154,"context_line":"  Ceilometer, this part is unclear to me right now."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"Optimization, can be done later:"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_45f7a259","line":154,"in_reply_to":"da86d52c_9f5494cb","updated":"2015-02-09 18:47:20.000000000","message":"Are there any \u0027daemon\u0027 libraries that exist that are asyncio compat, or simpler... (to replace the service.py stuff).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"f81484c5c25be99f77706120fe1d75accd342141","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"* CPython (the reference Python implementation) has a Giant Interpreter Lock"},{"line_number":205,"context_line":"  known as \"GIL\" which reduces the performances of native threads. PyPy has a"},{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_77fd736e","line":206,"updated":"2015-02-07 01:15:30.000000000","message":"GIL stands for \"Global Interpreter Lock\", not Giant.\n\nImproving upon GIL has nothing to do with async programming.  Both the GIL, and explicit async, squeeze all operations through a single CPU serially.  The GIL does not block on IO.  There are no performance gains to be had in this regard by async.\n\nSee Glyph\u0027s own admission of this here: https://glyph.twistedmatrix.com/2014/02/unyielding.html\n\n\"Unfortunately, “asynchronous” systems have often been evangelized by emphasizing a somewhat dubious optimization which allows for a higher level of I/O-bound concurrency than with preemptive threads, rather than the problems with threading as a programming model...the situation is almost always more complicated than that, when it comes to performance; context switching is rarely a bottleneck in real-world programs\"","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"* CPython (the reference Python implementation) has a Giant Interpreter Lock"},{"line_number":205,"context_line":"  known as \"GIL\" which reduces the performances of native threads. PyPy has a"},{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_e6f457d1","line":206,"updated":"2015-02-06 23:33:54.000000000","message":"Which projects would actually see performance lose due to this?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"* CPython (the reference Python implementation) has a Giant Interpreter Lock"},{"line_number":205,"context_line":"  known as \"GIL\" which reduces the performances of native threads. PyPy has a"},{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_6bac7e36","line":206,"in_reply_to":"da86d52c_77fd736e","updated":"2015-02-09 17:05:25.000000000","message":"You are probably right that the performance limitations caused by the GIL may not be seen in OpenStack, if most operations are I/O-bound.\n\n\"context switching is rarely a bottleneck in real-world programs\"\n\nYeah, that\u0027s why your micro-benchmark on function vs generator is not revelant here :-)\n\nNote : David Beazley identifies performances issues related to the GIL: splitting work in multiple threads may slow down the process instead of make it faster, just because of the GIL. His code is CPU-bound, the worst case for the GIL. This issue was fixed in Python 3.2. See for example:\nhttp://www.dabeaz.com/GIL/","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_86255b5e","line":209,"updated":"2015-02-06 23:33:54.000000000","message":"The same seems like it could be said about trillous/asyncio, at least with threads u have many many debuggers that u can use to see this kind of stuff...","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_ff8cb037","line":209,"in_reply_to":"da86d52c_86255b5e","updated":"2015-02-09 17:05:25.000000000","message":"My point is that, using asyncio, you control when your function (coroutine) can be interrupted: at each \"yield from\". With eventlet or threads, well, you don\u0027t know... With threads, it can be anywhere. With eventlet, it\u0027s difficult to guess if calling a function may switch or not.\n\nAgain, I\u0027m not saying that it\u0027s impossible to write correct code with threads. There are many thread-safe operations and it\u0027s not that hard to use locks. It\u0027s just that writing correct code with asyncio is simpler.\n\nI\u0027m not saying that asyncio avoids all classes of bugs. Asynchronous programming remains hard! Sorry.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":206,"context_line":"  STM project to drop it, but this project is experimental and it is not yet"},{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_65882623","line":209,"in_reply_to":"da86d52c_ff8cb037","updated":"2015-02-09 18:47:20.000000000","message":"I\u0027d almost want to leave these kind of statements out of the spec then; they are to biased and hard to agree on.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"fddde51e56d7e6a612609d59a189ba3a2f44a2fe","unresolved":false,"context_lines":[{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_611691a9","line":210,"updated":"2015-02-06 23:35:21.000000000","message":"At what scale is your openstack running; nothing even close to this is already causing issues ;)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_a6722d47","line":210,"in_reply_to":"da86d52c_611691a9","updated":"2015-02-09 17:05:25.000000000","message":"Sorry, I just picked 500 from my memory. It\u0027s maybe an old number :-) I don\u0027t know how to get a more realistic limit.\n\nA single user request may have to be splitted into many smaller parts which run concurrently, to get best performances. It would be nice to have an idea of how many eventlet greenthreads are running in nova for example.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":207,"context_line":"  faster than CPython with GIL."},{"line_number":208,"context_line":"* It\u0027s hard to detect race conditions when writing code and even harder to"},{"line_number":209,"context_line":"  detect them at runtime."},{"line_number":210,"context_line":"* It does not scale: the limit of the concurrency is usually around 500 threads"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_25762e3f","line":210,"in_reply_to":"da86d52c_a6722d47","updated":"2015-02-09 18:47:20.000000000","message":"As many as oslo.messaging executor spins up (at least for the non-wsgi components); afaik oslo.messaging is still the thing that spawns all the greenthreads that apps use (once they run with the service.py stuff).\n\nhttps://github.com/openstack/oslo.messaging/blob/master/oslo_messaging/_executors/base.py#L20\n\nSo I guess that\u0027s 64*N (where N is the number of service forks running?)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"},{"line_number":214,"context_line":"or processes."},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"asyncio uses native threads. For example, by default, resolving a hostname"},{"line_number":217,"context_line":"calls the ``getaddrinfo()`` function which is blocking: the function is"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_46b9a3eb","line":214,"updated":"2015-02-06 23:33:54.000000000","message":"Most of openstack isn\u0027t a web server though, so I\u0027m not sure this comparison is useful; sure some user-entrypoints for openstack are, but the rest isn\u0027t. And this is getting into territory that is hard to quantify since it highly depends on the architecture of both of those. I\u0027ve seen huge websites work with apache forking and know that it has worked out just fine...","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"89af5e2c644b8c55dada1ac688775be87aa94a3f","unresolved":false,"context_lines":[{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"},{"line_number":214,"context_line":"or processes."},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"asyncio uses native threads. For example, by default, resolving a hostname"},{"line_number":217,"context_line":"calls the ``getaddrinfo()`` function which is blocking: the function is"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_054f6abf","line":214,"in_reply_to":"da86d52c_060cd993","updated":"2015-02-09 18:47:20.000000000","message":"Sure, but knowing openstack we have to get pass the C100 first before getting to C10000 ;)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":211,"context_line":""},{"line_number":212,"context_line":"In the world of web servers, nginx usually win benchmarks against apache. nginx"},{"line_number":213,"context_line":"is asynchronous and event-driven, while apache was more designed to use threads"},{"line_number":214,"context_line":"or processes."},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"asyncio uses native threads. For example, by default, resolving a hostname"},{"line_number":217,"context_line":"calls the ``getaddrinfo()`` function which is blocking: the function is"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_060cd993","line":214,"in_reply_to":"da86d52c_46b9a3eb","updated":"2015-02-09 17:05:25.000000000","message":"\"nginx vs apache\" is not the best comparison. The C10K problem is a better reference:\n\nThe `C10K program \u003chttp://www.kegel.com/c10k.html\u003e`_ showed that asynchronous event-driven is the more efficient than threads to handle concurrent requests, at least for web servers.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"f81484c5c25be99f77706120fe1d75accd342141","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":"NA"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"Performance Impact"},{"line_number":251,"context_line":"------------------"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The first part only adds an optional support for trollius coroutines which has"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_d7f37f9d","line":250,"updated":"2015-02-07 01:15:30.000000000","message":"600% reduction of Python performance for basic functions calling into IO (all database-related code), which will be multiplied throughout thousands of database / IO-oriented functions throughout all Openstack code and related libraries.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":"NA"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"Performance Impact"},{"line_number":251,"context_line":"------------------"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The first part only adds an optional support for trollius coroutines which has"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_df628c15","line":250,"in_reply_to":"da86d52c_d7f37f9d","updated":"2015-02-09 17:05:25.000000000","message":"Again, IMO your microbenchmark is irrevelant","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"424dddfa3a16db62a02872bc2637e325ce426a50","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":"NA"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"Performance Impact"},{"line_number":251,"context_line":"------------------"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The first part only adds an optional support for trollius coroutines which has"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_f6f6bb8f","line":250,"in_reply_to":"da86d52c_d7f37f9d","updated":"2015-02-08 05:47:20.000000000","message":"This comment is worded very awfully and I apologize for that.    The 600% number only refers to my barebones test above, but in reality this is just the latency of the function itself, and in comparison to a real function may not represent that large a percentage of what the function does.   I\u0027ve also observed that Python 3 has improved the latency of throwing/catching a StopIteration by a sizable margin, about 50% of Py2K\u0027s latency.\n\nTo get more perspective on this, I applied a small change to the core of SQLAlchemy where it executes a statement, to run next() on an empty iterator and to receive the ResultProxy as the argument of a StopIteration catch.  Running this against some standard time-based benches reduces performance by about 10%.  This was just the central _execute_context() function, with a do-nothing system, so I might guesstimate perhaps 40% slower throughput in a real world system that has a lot more single-element iterators and StopIterations, combined with other function call overhead added by the basic routines of asyncio.   This is still a big deal, as I\u0027ve spent years squeezing out 5-10% incremental improvements across many areas of SQLAlchemy in each major release; within the context of that work, turning all return values into raises is a significant step backwards.   \n\nSo there is definitely a performance impact when a large number of function returns are turned into \"raise StopIteration\" calls, combined with the production and invocation of many more iterators, though it is obviously not applicable as a multiplier to each function individually, it just places more of a performance tax on functions which will add up in a cumulative sense.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":"NA"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"Performance Impact"},{"line_number":251,"context_line":"------------------"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"The first part only adds an optional support for trollius coroutines which has"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_a68f8dcb","line":250,"in_reply_to":"da86d52c_f6f6bb8f","updated":"2015-02-09 17:05:25.000000000","message":"I don\u0027t expect faster performances thanks to \"yield from\" but slow down :-) I expect better performances from async DB drivers like aiomysql or aiopg when sending multiple concurrent DB queries. Concurrency probably matters a lot for such benchmark.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"f81484c5c25be99f77706120fe1d75accd342141","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_7734934a","line":258,"updated":"2015-02-07 01:15:30.000000000","message":"This should be proven with benchmarks.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"bcc1896d4a8bc3a18f084dfd8d84d610f4cdbd35","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_82e4eb3c","line":258,"in_reply_to":"da86d52c_57603c35","updated":"2015-02-10 23:58:37.000000000","message":"Ludovic Gasc, the author of the benchmark wrote me that he tried to comment this issue, but his comment was not saved. Here is his comment:\n\nHi Michael,\n\nI\u0027m Ludovic Gasc. You don\u0027t know me, but I know you. I\u0027m the creator of API-Hour, and I\u0027ve made this benchmark on a kitchen table.\n\nTo help you to be in the same spirit as me after your comment, I propose something: Image a parallel world where OpenStack is written with only raw SQLs. Imagine that for each SQL query, each write the SQL query for each engine supported by OpenStack. In this world, you wrote DB-API and some DB connectors. Victor has written an OpenStack specification to propose to migrate step-by-step to an ORM, to avoid to write queries for each DB engine. Victor proposes to use SQLalchemy, a very good ORM, written by myself, and a proof that developer saves time with SQLalchemy instead of write raw SQL. [troll]In fact, you\u0027re telling me that ORM is an useless pattern, aren\u0027t you ? ;-)[/troll]\n\nNow that I\u0027ve your attention, back to the reality: First, I\u0027m really interested in by your feedbacks to improve my benchmark and methodology. Nevertheless, for your information, this WebService I\u0027ve used to benchmark is a real world example, it\u0027s on production for a big customer. It retrieves the list of agents with their telephony status. Why I compare Flask with API-Hour ? Simply because this WebService (and others) was written with Flask, we had a lot of performance issues with that. The customer has Java developers, their started to \"troll\" about Python performance issues. Finally, I\u0027ve found a really more efficient solution with AsyncIO + pre-API-Hour (multiprocess pattern).\n\nSecond, please don\u0027t kill the baby in the bathroom: certainly, AsyncIO should be more efficient. People, especially Victor, is working hard for that. But, asynchronous/coroutine pattern isn\u0027t a new fancy stuff to decrease developer productivity and performance: Start with NodeJS, this pattern is more and more included in new languages (Go...) but also in old fashion languages (Python, C#...). Async isn\u0027t a silver bullet, especially for intensive calculations, but for I/O, at least from my experience, it seems to be more efficient. Databases connexions are big I/O consumers, at least in Web applications, AsyncIO should maybe interesting for you, even if I can really understand your reaction: If one day, you integrate AsyncIO in SQLalchemy, you certainly need to rethink your internal architecture.\n\nFor me, it was really clever for Guido to take all good ideas of async frameworks of Python to create AsyncIO. Because, AsyncIO isn\u0027t only a library, it would be more and more the \"standard\" way to write async code with Python. Instead of each async Python framework must reinvent the wheel in each island, AsyncIO should help to have a \"lingua franca\" for async in Python. As you explained, when you start async in a project, you can\u0027t keep sync for the rest, everything should be async. It\u0027s like oriented object programming, you can\u0027t be object and procedural in the same time. In 2015, who writes a full-monty application with procedural only ? Maybe, one day, it would be the same for async pattern. It\u0027s always better to be the engine of a change that to endure the change. The only thing we don\u0027t know right now if async is only a temporary fashion buzzword or a paradigm change in IT world, like virtualisation. At least, for OpenStack, async seems to be already in the place with eventlet and tornado.\n\nThird, I can understand you don\u0027t believe me about benchmarks, I\u0027m nobody in Python community. But, FYI, API-Hour will participate to the next round of FrameworkBenchmark: https://www.techempower.com/benchmarks/ The guys behind that are Java people, they shouldn\u0027t have no bias about Python. Again, even if API-Hour would be on the top podium of Python category, it will mean only that, for this list of WebServices used for benchmark, API-Hour architecture is more efficient. Not true for all problems of the world. My hope about this benchmark it isn\u0027t to start a war with others sync Python frameworks, but to have some emulation between Pythonistas to find the solutions to increase performances. BTW, thanks a lot to share this link:http://techspot.zzzeek.org/2010/12/12/a-tale-of-three-profiles/ It\u0027s a lot interesting, at least for me.\n\nAnd finally, all Python community will win, because, at the end, maybe Python should considered as a fast language to write business logic AND brute performance, at least compare to others interpreted languages. My personal interest in that I\u0027m really tired to listen customers that Python is slow during presales meeting, I must fight each time against this bias. Certainly too slow for Google, but for most people, with a good architecture, Python it\u0027s very well.\n\nRegards.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_bf54f821","line":258,"in_reply_to":"da86d52c_7734934a","updated":"2015-02-09 17:05:25.000000000","message":"See for example `API Hour benchmark\n\u003chttps://github.com/Eyepea/API-Hour#quickndirty-http-benchmarks-on-a-kitchen-table\u003e`_\nwhich compares synchronous and asynchronous code for DB requests (using aiopg)\nand JSON serialization in a web server: asynchronous code can handle much more\nrequests in 30 seconds.\n\nThe author told me that he uses a pool of DB connections to get so good performances.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"b9074794df6c1f2632869f7c31b84d83b1845f08","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_e5ef711c","line":258,"in_reply_to":"da86d52c_82e4eb3c","updated":"2015-02-11 00:44:57.000000000","message":"Hi Ludovic -\n\nRegarding your first \"troll\" - I\u0027d say that analogy is broken.  SQLAlchemy\u0027s purpose\nis one of making programming patterns with SQL more high level and\ndeclarative, taking decisions that can be easily (or not so easily) automated\naway and doing so, removing the need for explicit boilerplate. AsyncIO is in\nsome ways the\n*opposite* of that - it takes an entirely predictable aspect of the program\n(when it has to do IO) and forces it to be *explicit*.   It seeks\nto add boilerplate in the name of decisions that can\u0027t be automated, rather\nthan removing boilerplate in the name of previous manual decisions that\n*can* be automated.   At the end of the day SQLAlchemy still brings out\na lot of its own often complicated patterns, but these are more on the\nside of up-front declarations for the purposes of automating work\nand reducing code verbosity and boilerplate in the bigger picture of large scale systems.\n\n\n\u003e First, I\u0027m really interested in by your feedbacks to improve my benchmark and methodology.\n\nWorking on it!   A real benchmark needs to compare psycopg2 async and sync\nas closely as possible, without frameworks getting in the way.  I notice that\nAPI-Hour combines async with multiprocessing.  Is the Flask example using\nmultiprocessing in the same way as well?    If not, how do you know the\ngreater throughput is due to async and not the multiprocessing?  That\u0027s just\none example.  Flask has a lot going on that gets in the way of this being\na raw test between async and non-async.\n\nAs an aside, I looked a lot through the benchmark code you had, and it doesn\u0027t seem to be runnable, because I could not find any mention of how the database schema gets created or where the data within the tables comes from.    It also seems to just work with a simple SELECT and a benchmark should have a lot more variety than that.    The Flask example also failed to set \"autocommit\u003d0\", turning off psycopg2\u0027s transaction control in the same way that is implicit with psycopg2 async, and I\u0027d also note that psycopg2 async doesn\u0027t have any ability to run an executemany().  I\u0027m quite sure that I can easily make benchmarks on the CRUD side that blow away any pure-Python async for this reason alone, but I will try to make my tests illustrate more comparable matchups as well.\n\n\u003e Async isn\u0027t a silver bullet, especially for intensive calculations, but for I/O, at least from my experience, it seems to be more efficient. Databases connexions are big I/O consumers, at least in Web applications\n\nMy hypothesis, which I am working to research further is this:  in a\nrelative sense, specific to Python, they are not. Database connections\nare extremely fast, compared to Python\u0027s extremely slow performance when it\ncomes to functions and methods in pure Python.  That is why I have\nillustrated a plain Python benchmark that illustrates MySQLdb doing\nthe same work as a PyMySQL script 1000% faster.   This is not an IO-\nbound situation when the interpreter is this slow.\n\n\u003e For me, it was really clever for Guido to take all good ideas of async frameworks of Python to create AsyncIO. Because, AsyncIO isn\u0027t only a library, it would be more and more the \"standard\" way to write async code with Python.\n\nAgree, and I am very happy about this, and I have already begun producing\nthe SQLAlchemy compatibility layer for this system, as the \"yield from\" technique\nallows me to maintain the vast majority of code as is, some replacements for\nkey methods is all that\u0027s needed and hopefully the maintenance burden won\u0027t\nbe extremely great (it will be somewhat significant, however).\n\nHowever, it seems unfortunate that right out of the gate, it\u0027s already being bypassed,\nbecause it doesn\u0027t work on Python 2.  This entire blueprint does not appear\nto in fact be proposing using the asycnio framework at all; it\u0027s proposing\nusing the Trollius system.  It would be IMO preferable to move to Python 3 first,\n*then* port to asyncio.\n\n\u003e At least, for OpenStack, async seems to be already in the place with eventlet and tornado.\n\nWhat should be mentioned again here is that Openstack started **entirely** on Tornado,\nwhich was then dumped, in favor of Twisted.  Twisted was then dumped, because it\nwas too difficult to deal with.   I think proposing that Openstack spends thousands of\nhours more reverting it *again* to an async model is really quite bold.\n\nThis is why I\u0027m researching my own benchmarks, in order to either\nillustrate definitively that async is in fact vastly more efficient,\neven in the case of extremely low IO-latency database calls, or to\nshow that it really doesn\u0027t help much at all in this area.   If the\nlatter case proves to be correct, I hope to make this available as a\nkey reason not to pursue asyncio as an across-the-board solution;\nnot because it would preclude\nSQLAlchemy, because at this point I\u0027m pretty confident I can keep\nSQLAlchemy along side within the asyncio community (and I\u0027m in fact\nreally happy about that, because as I\u0027ve said,  converting it to\nTwisted was looking like a total disaster... asyncio is actually doable),\nbut instead because it would be a profound waste of time to convert\nOpenstack yet again to another async programming paradigm, when it has already\ndumped two of them.   Nobody seems willing to provide a real benchmark\nillustrating very directly how async DB calls are faster than sync in\nsomewhat of a real-world situation, so I hope that I have the time to\ncomplete the work I\u0027m doing in this area.\nIt will save me vast amounts of time either way; either I no longer have\nto continue arguing that async is really not very effective for DB code\nbecause I will have proven myself wrong, or I will have a simple case to\nrefer to in order to refute this commonly heard claim.\n\nOverall, I think you and Victor have done a great service in any case, no\nmatter what the outcome.  I\u0027ve\nfinally looked at asyncio deeply and the effort to produce a real SQLAlchemy\nlayer is underway.   I\u0027ve been inspired to look into this more deeply\nas I\u0027ve been avoiding for many months due to the time consuming nature of it,\nbut now that effort is happening.   So both of you have had a great impact,\nthanks for that!","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"276685e204148e4450623144efde2e6326f67603","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_57603c35","line":258,"in_reply_to":"da86d52c_bf54f821","updated":"2015-02-09 18:15:45.000000000","message":"That example is *rife* with issues.\n\nFirst off, Flask is **not at all** a fast framework.   I am sure that the api-hour system is much simpler and has much more efficient Python code.   The way one can prove that API-hours speed here is due to asyncio is to show Python profiling and illustrate that both the api-hour and the Flask system are using the same number of Python function calls in aggregate.  I have no doubt at all that the Flask example is using a lot more function calls.         A real benchmark needs to strip away such prominently enormous differences in implementation to be taken seriously.\n\nAnother issue is that it is very true that async-explicit or gevent-style code can spin up a lot more database connections concurrently, because it\u0027s true that when you get to more than 20 threads in a Python interpreter, things start to fall over for sure.  Which means that yes, there still is some truth to the IO-bound equation in that you can get more throughput by having lots more concurrency.\n\nHowever, Openstack applications have their connection pools topped at 15 connections.  If you run a full devstack setup, then look at how many connections your MySQL database has, it\u0027s still easily in the 150-200 connections range, e.g. somewhat maxed out on a moderate system.  This is because Openstack runs a ton of Python processes - all those 5-15 connection pools add up quickly.   So this is another area where the theoretical gains of async, in that we can spin up more \"green\" threads, or the user-hand-coded equivalent of such, is not necessarily a gain that can just be applied to Openstack as it is.  The proposal here would need to show just how Openstack processes can be appropriately scaled up to be able to have 50-100 database connections concurrently in order to realize the kinds of gains one would see in that speed test.  \n\nThe speed test that you refer to up there is *exactly* the kind that Glyph himself refers to as not a \"real world\" application.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"3e0e9a58d8e381b315ef66088befcd65ef1cc749","unresolved":false,"context_lines":[{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_58d64d50","line":258,"in_reply_to":"da86d52c_e5ef711c","updated":"2015-02-11 14:27:42.000000000","message":"\u003e Overall, I think you and Victor have done a great service in any case, no matter what the outcome.\n\nThanks. I\u0027m quite happy to have this spec written, even it may be withdrawn. If the proposition is withdrawn, at least we will have a whole spec explaining why. I like the process, it\u0027s very similer to Python PEPs which are also a great success in Python.\n\nSomeone may use this spec to write a \"replace eventlet with threads\" spec ;-)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"},{"line_number":262,"context_line":"---------------------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_462a83e8","line":259,"updated":"2015-02-06 23:33:54.000000000","message":"Isn\u0027t there also a performance impact if you are using libraries that don\u0027t support the coroutine library (isn\u0027t that most of the libraries in existence?); so everytime u have to use one of these libraries u have to either block or shove it off into a thread-pool? Whats the standard practice for that?\n\nThought experiemnt that would be useful imho; how would one use sqlalchemy (it doesn\u0027t support coroutines), what would usage of it look like/behave like?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":256,"context_line":"The second part has an unknown impact on performances."},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"We can expect better performances with fully asynchronous clients."},{"line_number":259,"context_line":""},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"Other deployer impact"},{"line_number":262,"context_line":"---------------------"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_9f057416","line":259,"in_reply_to":"da86d52c_462a83e8","updated":"2015-02-09 17:05:25.000000000","message":"It\u0027s too early to reply in general.\n\nI don\u0027t know the overhead of calling blocking a function through loop.run_in_executor() (a pool of threads). If you don\u0027t call blocking functions with loop.run_in_executor(), you may limit the concurrency and not reach the optimal performances, but it may not be your bottleneck. You should focus on the bottleneck, not on each function call.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":398,"context_line":"``yield from ...``  ``yield From(...)``"},{"line_number":399,"context_line":"``yield from []``   ``yield From(None)``"},{"line_number":400,"context_line":"``return``          ``raise Return()``"},{"line_number":401,"context_line":"``return x``        ``raise Return(x)``"},{"line_number":402,"context_line":"``return x, y``     ``raise Return(x, y)``"},{"line_number":403,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":404,"context_line":""}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_c63d932e","line":401,"updated":"2015-02-06 23:33:54.000000000","message":"Sadface ``raise return()`` on this (although I know why its done like that).\n\nI just imagine all the commits that will have to be done to turn \u0027return\u0027 into \u0027raise return()\u0027 and then I cry, lol.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"276685e204148e4450623144efde2e6326f67603","unresolved":false,"context_lines":[{"line_number":399,"context_line":"``yield from []``   ``yield From(None)``"},{"line_number":400,"context_line":"``return``          ``raise Return()``"},{"line_number":401,"context_line":"``return x``        ``raise Return(x)``"},{"line_number":402,"context_line":"``return x, y``     ``raise Return(x, y)``"},{"line_number":403,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":404,"context_line":""},{"line_number":405,"context_line":"It is possible to write code working with trollius and asyncio in the same code"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_d788acc8","line":402,"updated":"2015-02-09 18:15:45.000000000","message":"I reviewed trollius in depth the other day and I agree that this code incompatibility is concerning.  There does not appear to be a clean upgrade path such that a Python 3 application can run cleanly on asyncio, unless we were building into tools like 3to2 in order to port code via search-and-replace at installation time.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"4fc34a8614de7021b2176f2cef120dc9ea63662d","unresolved":false,"context_lines":[{"line_number":399,"context_line":"``yield from []``   ``yield From(None)``"},{"line_number":400,"context_line":"``return``          ``raise Return()``"},{"line_number":401,"context_line":"``return x``        ``raise Return(x)``"},{"line_number":402,"context_line":"``return x, y``     ``raise Return(x, y)``"},{"line_number":403,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":404,"context_line":""},{"line_number":405,"context_line":"It is possible to write code working with trollius and asyncio in the same code"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_c4e8eb7e","line":402,"in_reply_to":"da86d52c_d788acc8","updated":"2015-02-09 22:58:40.000000000","message":"The spec proposes to use trollius on python 2 and python 3, to have the same code base. It means that other libraries should support trollius too. If a library already supports asyncio, it\u0027s much easier to port it to trollius, than having to rewrite it to be asynchronous. The quantity of work really depends on the library. I didn\u0027t port any library to trollius myself, but as I wrote below there are already \"trollius-ready\" libraries.\n\nTrollius has been designed to be able to easily convert your code base from trollius to asyncio. For example, From(obj) just returns obj: it\u0027s a no-op just to be able to replace \"yield From(...)\" pattern with \"yield from ...\". Trollius also supports running asyncio coroutines (when your application runs on Python 3.3+, since asyncio requires yield-from introduced in Python 3.3).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":405,"context_line":"It is possible to write code working with trollius and asyncio in the same code"},{"line_number":406,"context_line":"base if coroutines are not used, but only callbacks and futures. Some libraries"},{"line_number":407,"context_line":"already support asyncio and trollius like AutobahnPython (Websockets and WAMP),"},{"line_number":408,"context_line":"Pulsar and Tornado."},{"line_number":409,"context_line":""},{"line_number":410,"context_line":"Another option is to provide functions returning ``Future`` objects, so the"},{"line_number":411,"context_line":"caller can decide to use callback using ``fut.add_done_callback(callback)`` or"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_06488bcb","line":408,"updated":"2015-02-06 23:33:54.000000000","message":"Ya, so it might be quite useful to see what in:\n\nhttps://github.com/openstack/requirements/blob/master/global-requirements.txt\n\nDoes or doesn\u0027t, since the ones u listed I don\u0027t think openstack is using so aren\u0027t exactly relevant to list (as nothing is using them anyway, and without serious refactoring they likely won\u0027t be switched to).","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"276685e204148e4450623144efde2e6326f67603","unresolved":false,"context_lines":[{"line_number":411,"context_line":"caller can decide to use callback using ``fut.add_done_callback(callback)`` or"},{"line_number":412,"context_line":"to use coroutines (``yield From(fut)`` for Trollius, or ``yield from fut`` for"},{"line_number":413,"context_line":"Tulip). This option is used by the `aiodns \u003chttps://github.com/saghul/aiodns\u003e`_"},{"line_number":414,"context_line":"project for example."},{"line_number":415,"context_line":""},{"line_number":416,"context_line":"On Python 3.3 and newer, Trollius supports also asyncio coroutines. The"},{"line_number":417,"context_line":"trollius module is compatible with asyncio, the opposite is false."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_3753c83a","line":414,"updated":"2015-02-09 18:15:45.000000000","message":"i looked at aiodns and it is like, a 50 line library that uses exactly one \"future\", and I really did not get a sense of how a codebase with a lot of \"yield from\" and \"return\" calls could be reworked to only return Future objects.  This is actually an approach I at least want to consider for SQLAlchemy though I\u0027m concerned the futures add even more function call overhead.   Can you please provide more complete documentation and examples as to how to convert standard asyncio function calls to only use Future objects?","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"4fc34a8614de7021b2176f2cef120dc9ea63662d","unresolved":false,"context_lines":[{"line_number":411,"context_line":"caller can decide to use callback using ``fut.add_done_callback(callback)`` or"},{"line_number":412,"context_line":"to use coroutines (``yield From(fut)`` for Trollius, or ``yield from fut`` for"},{"line_number":413,"context_line":"Tulip). This option is used by the `aiodns \u003chttps://github.com/saghul/aiodns\u003e`_"},{"line_number":414,"context_line":"project for example."},{"line_number":415,"context_line":""},{"line_number":416,"context_line":"On Python 3.3 and newer, Trollius supports also asyncio coroutines. The"},{"line_number":417,"context_line":"trollius module is compatible with asyncio, the opposite is false."}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_8418b385","line":414,"in_reply_to":"da86d52c_3753c83a","updated":"2015-02-09 22:58:40.000000000","message":"The hearth of asyncio is only made of callbacks. Tasks are a convinient layer designed on top of callbacks. Futures are more convinient than callbacks and you can use them with callbacks (fut.add_done_callback(cb)) or in coroutines (yield from fut).\n\nIf you want to support trollius with a future, basically you don\u0027t use yield nor yield from. Basic example:\n\ndef later(value):\n  fut \u003d asyncio.Future()\n  loop.call_soon(fut.set_result, value)\n  return fut\n\nlater() returns a future which has no result yet. The result will be known \"later\". Futures can be used easily in libraries already written with callbacks. It\u0027s usually the case for libraries written for Twisted, Tornado or implemented in C with callbacks.","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"e7a9136b379c4236ff8e5b9cb28a288bea107d51","unresolved":false,"context_lines":[{"line_number":424,"context_line":""},{"line_number":425,"context_line":"In OpenStack, eventlet cannot be replaced with asyncio in all projects in a"},{"line_number":426,"context_line":"single commit. The OpenStack development is made with small and limited"},{"line_number":427,"context_line":"changes. To have a smooth transition, the `aioeventlet project"},{"line_number":428,"context_line":"\u003chttp://aioeventlet.readthedocs.org/\u003e`_ was written to support the asyncio API"},{"line_number":429,"context_line":"on top of eventlet. It makes possible to add support for asyncio coroutines to"},{"line_number":430,"context_line":"an existing OpenStack component without having to replace immediatly its"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_268f4fce","line":427,"updated":"2015-02-06 23:33:54.000000000","message":"Many many many many many small mannnnny changes ;)","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"0201fccb439d25b19371ef64bfeee1de6fad7e06","unresolved":false,"context_lines":[{"line_number":460,"context_line":"* December 3, 2014: two patches posted to requirements:"},{"line_number":461,"context_line":"  `Add aioeventlet dependency \u003chttps://review.openstack.org/#/c/138750/\u003e`_"},{"line_number":462,"context_line":"  and `Drop greenio dependency \u003chttps://review.openstack.org/#/c/138748/\u003e`_."},{"line_number":463,"context_line":"* Novembre 23, 2014: two patches posted to Oslo Messaging:"},{"line_number":464,"context_line":"  `Add a new aioeventlet executor \u003chttps://review.openstack.org/#/c/136653/\u003e`_"},{"line_number":465,"context_line":"  and `Add an optional executor callback to dispatcher"},{"line_number":466,"context_line":"  \u003chttps://review.openstack.org/#/c/136652/\u003e`_"}],"source_content_type":"text/x-rst","patch_set":1,"id":"da86d52c_9fb219e3","line":463,"updated":"2015-02-09 17:05:25.000000000","message":"typo: November","commit_id":"eda2755d948c0a71e87674620de565ad6d36da46"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"bb0bd86a37399d2f44bb75a41a286559ff991bf1","unresolved":false,"context_lines":[{"line_number":24,"context_line":"The spec is focused on Oslo Messaging and Ceilometer projects. More OpenStack"},{"line_number":25,"context_line":"components may be modified later if the Ceilometer port to asyncio is"},{"line_number":26,"context_line":"successful. Ceilometer will be used to find and solve technical issues with"},{"line_number":27,"context_line":"asyncio, so the same solutions can be used on other OpenStack components."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":30,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_c5326d0f","line":27,"updated":"2015-02-11 01:20:04.000000000","message":"Makes me feel sorta bad for ceilometer users that they are the test bed for this (but hopefully it goes well).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9664,"name":"amrith","email":"amrith.kumar@gmail.com","username":"amrith"},"change_message_id":"59bb5b32250a238d56f6a47a4eac2e20dce80f5c","unresolved":false,"context_lines":[{"line_number":53,"context_line":"This section only gives some examples of eventlet issues. There are more"},{"line_number":54,"context_line":"eventlet issues, but tricky issues are not widely discussed and so not well"},{"line_number":55,"context_line":"known. Most interesting issues are issues caused by the design of eventlet,"},{"line_number":56,"context_line":"especially the monkey-patching of the Python standard library."},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Eventlet itself is not really evil. Most issues come from the monkey-patching."},{"line_number":59,"context_line":"The problem is that eventlet is almost always used with monkey-patching in"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_b2267d14","line":56,"updated":"2015-02-11 17:33:59.000000000","message":"amen to that!!","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9664,"name":"amrith","email":"amrith.kumar@gmail.com","username":"amrith"},"change_message_id":"59bb5b32250a238d56f6a47a4eac2e20dce80f5c","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Eventlet itself is not really evil. Most issues come from the monkey-patching."},{"line_number":59,"context_line":"The problem is that eventlet is almost always used with monkey-patching in"},{"line_number":60,"context_line":"OpenStack."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"The implementation of the monkey-patching is fragile. It\u0027s easy to forget to"},{"line_number":63,"context_line":"patch a function or have issues when the standard library is modified. The"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_b2dbddeb","line":60,"updated":"2015-02-11 17:33:59.000000000","message":"Is there any other way to use eventlet? From what I\u0027ve found the only way is through monkey-patching and this is a very non-trivial way of doing things (as someone who\u0027s written self-modifying and self-replicating code)","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Eventlet itself is not really evil. Most issues come from the monkey-patching."},{"line_number":59,"context_line":"The problem is that eventlet is almost always used with monkey-patching in"},{"line_number":60,"context_line":"OpenStack."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"The implementation of the monkey-patching is fragile. It\u0027s easy to forget to"},{"line_number":63,"context_line":"patch a function or have issues when the standard library is modified. The"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_6115b19a","line":60,"in_reply_to":"da86d52c_b2dbddeb","updated":"2015-02-13 15:04:50.000000000","message":"It is possible to use eventlet without monkey-patching, but I\u0027m not sure that it\u0027s an acceptable choice for most OpenStack applications. Monkey-patching is probably required to be able to handle more than one request at the same time (required to have concurrency...).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9664,"name":"amrith","email":"amrith.kumar@gmail.com","username":"amrith"},"change_message_id":"59bb5b32250a238d56f6a47a4eac2e20dce80f5c","unresolved":false,"context_lines":[{"line_number":59,"context_line":"The problem is that eventlet is almost always used with monkey-patching in"},{"line_number":60,"context_line":"OpenStack."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"The implementation of the monkey-patching is fragile. It\u0027s easy to forget to"},{"line_number":63,"context_line":"patch a function or have issues when the standard library is modified. The"},{"line_number":64,"context_line":"eventlet port to Python 3 showed how the patcher highly depends on the standard"},{"line_number":65,"context_line":"library. A recent eventlet change (v0.16) \"turns off __builtin__ monkey"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_f22b9592","line":62,"updated":"2015-02-11 17:33:59.000000000","message":"Monkey patching is also done at the process level. So it is done across all threads and sometimes that\u0027s not what you want. Sometimes it is downright bad (such as during CI testing).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":100,"name":"Johannes Erdfelt","email":"johannes@erdfelt.com","username":"johannes.erdfelt"},"change_message_id":"ad8c1f5c836a798e342bc05c272bfc2383d6ee38","unresolved":false,"context_lines":[{"line_number":114,"context_line":"log() becomes asynchronous, you have no reminder that you have to take care of"},{"line_number":115,"context_line":"race conditions during a review of the change. With asyncio, you must add"},{"line_number":116,"context_line":"\"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your"},{"line_number":117,"context_line":"code becomes asynchronous.\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Disagreements:"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_d4e3e131","line":117,"updated":"2015-02-11 16:53:45.000000000","message":"There is a non-trivial amount of Nova code that is asynchronous anyway because there are multiple processes running.\n\nFor example, nova-api can be run as multiple processes. This is for scaling reasons. You could write code that is explicitly asynchronous in that case (or even single threaded!) and you would still have to deal with concurrency from the other nova-api processes (which may even be on other hosts).\n\nIn the case of multiple processes, like nova-api, the code written in that transfer() function still has a race condition even without the log calls.\n\nIt\u0027s a mistake to frame this as an explicit vs implicit asynchronous decision. Since we use multiple processes for nova-api, the decision to be implicitly asynchronous has already been made for us.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":114,"context_line":"log() becomes asynchronous, you have no reminder that you have to take care of"},{"line_number":115,"context_line":"race conditions during a review of the change. With asyncio, you must add"},{"line_number":116,"context_line":"\"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your"},{"line_number":117,"context_line":"code becomes asynchronous.\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Disagreements:"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_9712e707","line":117,"in_reply_to":"da86d52c_30826ec8","updated":"2015-02-13 15:04:50.000000000","message":"\u003e +1 to that, in distributed systems (like openstack); u have to get used to implicitly asynchronous (and imho the earlier u get used to the concept(s) the better...)\n\nI don\u0027t see the link between implicit async in nova and the fact that nova runs child processes.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":100,"name":"Johannes Erdfelt","email":"johannes@erdfelt.com","username":"johannes.erdfelt"},"change_message_id":"9fea2e6809d7f7cc9d56e29230cd6c1356ab0cf1","unresolved":false,"context_lines":[{"line_number":114,"context_line":"log() becomes asynchronous, you have no reminder that you have to take care of"},{"line_number":115,"context_line":"race conditions during a review of the change. With asyncio, you must add"},{"line_number":116,"context_line":"\"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your"},{"line_number":117,"context_line":"code becomes asynchronous.\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Disagreements:"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_dd8254c7","line":117,"in_reply_to":"da86d52c_9712e707","updated":"2015-02-17 17:14:15.000000000","message":"\u003e I don\u0027t see the link between implicit async in nova and the fact that nova runs child processes.\n\nThis is the difference between concurrency and parallelism.\n\nBoth are used in Openstack.\n\nThe existing concurrency solution is eventlet. You are proposing replacing it with asyncio.\n\nThe existing parallelism solution is multiple processes.\n\nWhile you can avoid some race conditions with an explictly asynchronous solution, it does nothing if there is parallelism involved. Nova has parallelism.\n\nAs a result, the claim that using an explicitly asynchronous solution avoids a class of bugs is only true if it fits within a specific set of restrictions (ie no parallelism). Nova (at least) doesn\u0027t fit into that. If you think that asyncio is a cure for race conditions in Nova, then you\u0027ll introduce race conditions regardless. This is dangerous.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"adc58dca2ec7e5b6c11dd919869499f529d42c2e","unresolved":false,"context_lines":[{"line_number":114,"context_line":"log() becomes asynchronous, you have no reminder that you have to take care of"},{"line_number":115,"context_line":"race conditions during a review of the change. With asyncio, you must add"},{"line_number":116,"context_line":"\"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your"},{"line_number":117,"context_line":"code becomes asynchronous.\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Disagreements:"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_30826ec8","line":117,"in_reply_to":"da86d52c_d4e3e131","updated":"2015-02-12 07:04:22.000000000","message":"+1 to that, in distributed systems (like openstack); u have to get used to implicitly asynchronous (and imho the earlier u get used to the concept(s) the better...)","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":114,"context_line":"log() becomes asynchronous, you have no reminder that you have to take care of"},{"line_number":115,"context_line":"race conditions during a review of the change. With asyncio, you must add"},{"line_number":116,"context_line":"\"yield from\" before log(): it\u0027s a nice reminder to say \"hey, be careful: your"},{"line_number":117,"context_line":"code becomes asynchronous.\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"Disagreements:"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_375cdbf0","line":117,"in_reply_to":"da86d52c_d4e3e131","updated":"2015-02-13 15:04:50.000000000","message":"I didn\u0027t say that asyncio solves all problems in the world. It only reduces the risk of race conditions, of some kinds of race conditions if you prefer.\n\n\u003e In the case of multiple processes, like nova-api, the code written\n\u003e in that transfer() function still has a race condition even without\n\u003e the log calls.\n\nBy the way, I read that the subprocess module is *not* monkey-patched in OpenStack (I don\u0027t know why, does anyone know?). Is there an API to \"poll\" a subprocess asynchrously with eventlet in OpenStack?\n\nasyncio has efficient code to handle child processes: pipes (stdin, stdout and stderr) are watched asynchronously, and asyncio doesn\u0027t need polling to wait for process exit (it registers a signal handler for SIGCHLD).\n\nYou can control asynchronously multiple child processes with asyncio. For example, you can ensure that a sequence of programs are executed in a sequential order, but concurrent requests may run other programs in parallel.\n\nAgain, I\u0027m not saying that you must use that or that it avoids issues, it\u0027s just that asyncio adds new ways to handle subprocesses, which are not currrently possible using eventlet.\n\nExample to serialize the execution of two processes but continue to handle other requests in parallel:\n\n@asyncio.coroutine\ndef handle_request(index):\n    text \u003d yield from run_program(\u0027print(\"Hello\")\u0027)\n    print(\"Request #%s: %s\" % (index, text))\n\n    text +\u003d yield from run_program(\u0027print(\" World!\")\u0027)\n    print(\"Request #%s: %s\" % (index, text))\n\nFull (working) code with an example of output (the code uses random sleep to simulate high system load):\nhttps://bitbucket.org/haypo/asyncio_staging/src/2776c32eded932322f121dac4b140777852ea88e/multiple_processes.py?at\u003ddefault\n\nIn this example, each request runs 2 programs sequentially, but 5 requests are running in parallel. The maximum number of parallel programs is the number of running requests (5 at the beginning, and then it decreases).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"bb0bd86a37399d2f44bb75a41a286559ff991bf1","unresolved":false,"context_lines":[{"line_number":120,"context_line":""},{"line_number":121,"context_line":"* Michael Bayer disagrees with Glyph\u0027s post. Threads are used virtually"},{"line_number":122,"context_line":"  everywhere in software, for decades. They aren\u0027t perfect but they are"},{"line_number":123,"context_line":"  certainly not as awful as Glyph describes."},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"See also general articles about asynchronous programming:"},{"line_number":126,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_180cec3a","line":123,"updated":"2015-02-11 01:20:04.000000000","message":"+1\n\nThat damn operating system scheduler decides to swap out the process and people seem to make programs work with that ;)\n\nThe world hasn\u0027t fallen apart due to preemptive scheduling afaik.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":100,"name":"Johannes Erdfelt","email":"johannes@erdfelt.com","username":"johannes.erdfelt"},"change_message_id":"ad8c1f5c836a798e342bc05c272bfc2383d6ee38","unresolved":false,"context_lines":[{"line_number":156,"context_line":"* asyncio requires Python 3.3 or newer, while OpenStack must support Python"},{"line_number":157,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":158,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":159,"context_line":"  project is actively developed and its community is active."},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"Trollius has a large test suite of 883 tests. It is tested on Linux, Windows,"},{"line_number":162,"context_line":"Mac OS X, FreeBSD, etc. asyncio is tested in a continuous integration"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_149659f0","line":159,"updated":"2015-02-11 16:53:45.000000000","message":"I don\u0027t know if this is a list of drawbacks for just asyncio or for the general concept if using an explicit async library, but the biggest drawback for explicit async is that it requires all code (including third party libraries) to explicitly support it. Not only is it a huge amount of work, it\u0027s not even clear third-party libraries are interested in supporting that use case.\n\nThis is why eventlet has monkey patching, even if everyone hates it. It\u0027s the only way to get most code to play nicely without native threads or processes.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":156,"context_line":"* asyncio requires Python 3.3 or newer, while OpenStack must support Python"},{"line_number":157,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":158,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":159,"context_line":"  project is actively developed and its community is active."},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"Trollius has a large test suite of 883 tests. It is tested on Linux, Windows,"},{"line_number":162,"context_line":"Mac OS X, FreeBSD, etc. asyncio is tested in a continuous integration"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_171517e5","line":159,"in_reply_to":"da86d52c_149659f0","updated":"2015-02-13 15:04:50.000000000","message":"\u003e This is why eventlet has monkey patching, even if everyone hates it.\n\nI don\u0027t think that monkey patching is the best solution. Threads are a different way to run blocking code in parallel. According to Glyph\u0027s article, green threads have the same issues than threads, so using threads without monkey patching may be a better approach than eventlet.\n\nBut I\u0027m not sure that threads are as easy to use as eventlet. Eventlet provides many high level classes and OpenStack was written for its API. Using threads may also require to rework OpenStack code, as required for asyncio.\n\nI didn\u0027t think so much about threads, so I may be completly wrong.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":100,"name":"Johannes Erdfelt","email":"johannes@erdfelt.com","username":"johannes.erdfelt"},"change_message_id":"9fea2e6809d7f7cc9d56e29230cd6c1356ab0cf1","unresolved":false,"context_lines":[{"line_number":156,"context_line":"* asyncio requires Python 3.3 or newer, while OpenStack must support Python"},{"line_number":157,"context_line":"  2.7. This issue was solved with the Trollius project, see below."},{"line_number":158,"context_line":"* asyncio is young and may have more bugs than other projects. However the"},{"line_number":159,"context_line":"  project is actively developed and its community is active."},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"Trollius has a large test suite of 883 tests. It is tested on Linux, Windows,"},{"line_number":162,"context_line":"Mac OS X, FreeBSD, etc. asyncio is tested in a continuous integration"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_bdc92027","line":159,"in_reply_to":"da86d52c_171517e5","updated":"2015-02-17 17:14:15.000000000","message":"I\u0027m not familiar with other OpenStack code, but Nova minimally uses eventlet APIs.\n\nIt would be much much less work to switch to native threads than to switch to asyncio.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"adc58dca2ec7e5b6c11dd919869499f529d42c2e","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"Switch from implicit asynchronous programming (eventlet using greenthreads) to"},{"line_number":205,"context_line":"explicit asynchronous programming (trollius coroutines using ``yield``). Need"},{"line_number":206,"context_line":"to modify OpenStack Common Libraries and applications. Modifications can be"},{"line_number":207,"context_line":"done step by step, the switch will take more than 6 months."},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"The first application candidate is Ceilometer. The Ceilometer project is young,"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_90515a64","line":206,"updated":"2015-02-12 07:04:22.000000000","message":"I\u0027m pretty sure your going to have to modify more than just openstack common libraries for this one...","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":203,"context_line":""},{"line_number":204,"context_line":"Switch from implicit asynchronous programming (eventlet using greenthreads) to"},{"line_number":205,"context_line":"explicit asynchronous programming (trollius coroutines using ``yield``). Need"},{"line_number":206,"context_line":"to modify OpenStack Common Libraries and applications. Modifications can be"},{"line_number":207,"context_line":"done step by step, the switch will take more than 6 months."},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"The first application candidate is Ceilometer. The Ceilometer project is young,"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_f7aa4370","line":206,"in_reply_to":"da86d52c_90515a64","updated":"2015-02-13 15:04:50.000000000","message":"Ok, I should add a section explaining how to handle blocking libraries without modying them. In short, the answer is loop.run_in_executor() or just make them block (it\u0027s fine too in many cases).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"c396ea76642b952d3d23393debea0fa147367d22","unresolved":false,"context_lines":[{"line_number":333,"context_line":"Eventlet"},{"line_number":334,"context_line":"~~~~~~~~"},{"line_number":335,"context_line":""},{"line_number":336,"context_line":"Keep eventlet which is already used."},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"eventlet is based on greenlet which allows to interrupt any function and"},{"line_number":339,"context_line":"restart it later, as coroutines but implicitly."}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_709c135e","line":336,"updated":"2015-02-11 11:17:09.000000000","message":"Hum, there is maybe another option that may be discussed: drop eventlet monkey-patching. I would prepare the code for asyncio (explicit async). But I have no concrete plan to do that. I\u0027m not sure that it\u0027s even technically possible.\n\neventlet monkey-patching is required to handle concurrent client requests. Without monkey-patching, many libraries are simply blocking.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":100,"name":"Johannes Erdfelt","email":"johannes@erdfelt.com","username":"johannes.erdfelt"},"change_message_id":"9fea2e6809d7f7cc9d56e29230cd6c1356ab0cf1","unresolved":false,"context_lines":[{"line_number":377,"context_line":""},{"line_number":378,"context_line":"* Programing with threads (native threads or green threads) is hard because the"},{"line_number":379,"context_line":"  code can be interrupted anywhere. It is harder to write \"thread-safe\" code"},{"line_number":380,"context_line":"  (ex: protecting shared data with locks) than to write asyncio code."},{"line_number":381,"context_line":"* CPython (the reference Python implementation) has a Global Interpreter Lock"},{"line_number":382,"context_line":"  (\"GIL\") which reduces the performances of native threads. Only one Python"},{"line_number":383,"context_line":"  instruction can be executed at the same time. The GIL is released for I/O"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_7d7b28be","line":380,"updated":"2015-02-17 17:14:15.000000000","message":"It has to happen anyway because of parallelism we already have. asyncio isn\u0027t a cure for this.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"bb0bd86a37399d2f44bb75a41a286559ff991bf1","unresolved":false,"context_lines":[{"line_number":382,"context_line":"  (\"GIL\") which reduces the performances of native threads. Only one Python"},{"line_number":383,"context_line":"  instruction can be executed at the same time. The GIL is released for I/O"},{"line_number":384,"context_line":"  operation. PyPy has a STM project to drop it, but this project is"},{"line_number":385,"context_line":"  experimental and it is not yet faster than CPython with GIL."},{"line_number":386,"context_line":""},{"line_number":387,"context_line":"The `C10K program \u003chttp://www.kegel.com/c10k.html\u003e`_ showed that asynchronous"},{"line_number":388,"context_line":"event-driven is the more efficient than threads to handle concurrent requests,"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_583f44b4","line":385,"updated":"2015-02-11 01:20:04.000000000","message":"Seems to be getting better @ http://speed.pypy.org/ (it looks faster at least with those graphs/tests there).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"9696bd3792ff8fd8b5811645352b5389933b50bd","unresolved":false,"context_lines":[{"line_number":382,"context_line":"  (\"GIL\") which reduces the performances of native threads. Only one Python"},{"line_number":383,"context_line":"  instruction can be executed at the same time. The GIL is released for I/O"},{"line_number":384,"context_line":"  operation. PyPy has a STM project to drop it, but this project is"},{"line_number":385,"context_line":"  experimental and it is not yet faster than CPython with GIL."},{"line_number":386,"context_line":""},{"line_number":387,"context_line":"The `C10K program \u003chttp://www.kegel.com/c10k.html\u003e`_ showed that asynchronous"},{"line_number":388,"context_line":"event-driven is the more efficient than threads to handle concurrent requests,"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_dc4b1b85","line":385,"in_reply_to":"da86d52c_583f44b4","updated":"2015-02-11 10:35:11.000000000","message":"PyPy *is* much faster than CPython. But PyPy still has a GIL.\n\nI\u0027m talking about the \"STM\" flavor of PyPy. The latest known benchmark can be found at:\nhttp://morepypy.blogspot.fr/2014/11/tornado-without-gil-on-pypy-stm.html\n\nOn the Tornado benchmark, PyPy STM using 4 cores is slower (max: 6 requests/sec) than PyPy using only 1 core (max: 7 req/sec). I would expect PyPy STM to be as fast, or... faster! PyPy STM is very young and still experimental. It\u0027s not ready for the production.\n\nWhen used \"correctly\", the GIL does not limit performances. For example, \"CPU-bound\" only impacts pure Python code. I already wrote once a md5sum.py proof-of-concept which was 4x faster than system md5sum (written in C), when I modified hashlib to release the GIL. The GIL is already released for all I/O operations (almost all system calls for example).\n\nThe md5sum.py can be found attached to the issue:\nhttp://bugs.python.org/issue4751\n\n(The hashlib optimization is part of Python 2.7, at least recent minor versions.)","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"d8b7fee4d6a0a41bb077abc9bc62cb09f2912b4d","unresolved":false,"context_lines":[{"line_number":391,"context_line":"The `Unyielding \u003chttps://glyph.twistedmatrix.com/2014/02/unyielding.html\u003e`_"},{"line_number":392,"context_line":"article explains how bad are threads and that threads should be avoided. Native"},{"line_number":393,"context_line":"threads should be avoided, but also implicit coroutines like the green threads"},{"line_number":394,"context_line":"of eventlet."},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"Disagreements:"},{"line_number":397,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_be6548e2","line":394,"updated":"2015-02-12 10:13:46.000000000","message":"Stopped reading after his strawman problem description of threading. Sure, if you write threaded code using lots of global state you\u0027re heading for disaster, or at least a ton of locks. You can design anything badly if you don\u0027t take the time to understand it.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"cd06864659e4acb70f3aa902c27c535a66f79f19","unresolved":false,"context_lines":[{"line_number":410,"context_line":"David Beazley identified performances issues related to the GIL: see"},{"line_number":411,"context_line":"`Understanding the Python GIL \u003chttp://www.dabeaz.com/GIL/\u003e`_. Splitting a"},{"line_number":412,"context_line":"CPU-bound task into multiple threads may slow down the task instead of making"},{"line_number":413,"context_line":"it faster, just because of the GIL. CPU-bound code is the worst case for the"},{"line_number":414,"context_line":"GIL. The GIL has been rewritten in Python 3.2 to enhance performances. The"},{"line_number":415,"context_line":"optimization will not be backported to Python 2.7."},{"line_number":416,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_e0e8e8b4","line":413,"updated":"2015-02-12 17:18:44.000000000","message":"Thankfully I didn\u0027t think that much of openstack was CPU bound (but instead IO bound; the exception maybe being keystone).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":410,"context_line":"David Beazley identified performances issues related to the GIL: see"},{"line_number":411,"context_line":"`Understanding the Python GIL \u003chttp://www.dabeaz.com/GIL/\u003e`_. Splitting a"},{"line_number":412,"context_line":"CPU-bound task into multiple threads may slow down the task instead of making"},{"line_number":413,"context_line":"it faster, just because of the GIL. CPU-bound code is the worst case for the"},{"line_number":414,"context_line":"GIL. The GIL has been rewritten in Python 3.2 to enhance performances. The"},{"line_number":415,"context_line":"optimization will not be backported to Python 2.7."},{"line_number":416,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_57078f81","line":413,"in_reply_to":"da86d52c_e0e8e8b4","updated":"2015-02-13 15:04:50.000000000","message":"Good to know!","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"b480526169cfbf076bcef4e65ac766f05a1de834","unresolved":false,"context_lines":[{"line_number":458,"context_line":"* Michael Bayer is concerned on performance overhead of coroutines. On the"},{"line_number":459,"context_line":"  microbenchmark `bench_generator.py"},{"line_number":460,"context_line":"  \u003chttps://bitbucket.org/haypo/asyncio_staging/src/2f89fbdc7c12bd2541071648018ab9d484d79703/bench_generator.py\u003e`_,"},{"line_number":461,"context_line":"  consuming a generator takes 951 ns whereas calling a function takes 228 ns:"},{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_83d02d20","line":461,"updated":"2015-02-12 10:00:31.000000000","message":"951ns \u003d\u003d 0.951ms\n228ns \u003d\u003d 0.228ms","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"b480526169cfbf076bcef4e65ac766f05a1de834","unresolved":false,"context_lines":[{"line_number":461,"context_line":"  consuming a generator takes 951 ns whereas calling a function takes 228 ns:"},{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_43aab585","line":464,"updated":"2015-02-12 10:00:31.000000000","message":"723ns \u003d\u003d 0.723ms","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"b480526169cfbf076bcef4e65ac766f05a1de834","unresolved":false,"context_lines":[{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_e3980977","line":465,"updated":"2015-02-12 10:00:31.000000000","message":"A database query typically takes more than 50 times longer than the slowest method mentioned above. Amdahls\u0027s law suggests that optimisation there may be misdirected, unless there\u0027s more to this than is stated here.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_7781f3c2","line":465,"in_reply_to":"da86d52c_4e41eca7","updated":"2015-02-13 15:04:50.000000000","message":"That\u0027s a good question. Does performances matter more than time to develop OpenStack? It\u0027s probably a matter of compromise.\n\n(I consider that asyncio should reduce the time to develop OpenStack, since we will have less bugs.)\n\nIf the code to handle the database is slower, the slowdown should be compared to the (potential) speedup of running more I/O operations asynchrnously (and so handling more requests in parallel).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"925ad20de1932b94fc1d2c7f2edffb8cde3f8d4b","unresolved":false,"context_lines":[{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_0b916bf1","line":465,"in_reply_to":"da86d52c_7781f3c2","updated":"2015-02-13 16:39:15.000000000","message":"\u003e since we will have less bugs.\n\nthis remains a hypothetical with zero proof that most of us disagree with.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"4e9647e2f5c51443a9efd8ec91aee20c7fa6616c","unresolved":false,"context_lines":[{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_4e41eca7","line":465,"in_reply_to":"da86d52c_e3980977","updated":"2015-02-12 15:29:15.000000000","message":"First off, that\u0027s a *minimal* coroutine.    A real execute call might have a dozen or more in play to get one statement over the wire (and more per result row too).   So they add up.\n\nSecondly, if program A and program B both run the identical database queries, but program B adds 20% overhead to every query, which program is faster?   \n\nThe Python interpreter, even with fairly simple and rudimental code, can easily produce CPU overhead to drown out all but the very slowest database IO.    Try out the benchmark script at https://wiki.openstack.org/wiki/PyMySQL_evaluation for a simple illustration.\n\nAs for a real asyncio/ threading benchmark, I\u0027m getting independent folks to review my benchmark methodology before releasing them, but so far they seem to illustrate this effect at scale very plainly, in terms of asyncio (and specifically aiopg).","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d9604450b30c35f8d49b893db95a13ea789990da","unresolved":false,"context_lines":[{"line_number":462,"context_line":"  consuming a generator is 4.2x slower than calling a function. Basically, the"},{"line_number":463,"context_line":"  microbenchmark measures the time to raise an exception (``StopIteration``)"},{"line_number":464,"context_line":"  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms"},{"line_number":465,"context_line":"  or less."},{"line_number":466,"context_line":""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"Other deployer impact"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_d7f29f9a","line":465,"in_reply_to":"da86d52c_e3980977","updated":"2015-02-13 15:04:50.000000000","message":"Well, I\u0027m not sure that these raw numbers from a *micro-benchmark* are really useful. But it\u0027s better than nothing!","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"2743f58e8b8ab810a19fd8ea1d8c6592039d7fe5","unresolved":false,"context_lines":[{"line_number":704,"context_line":"* `bottle: Greenlets to the rescue"},{"line_number":705,"context_line":"  \u003chttp://bottlepy.org/docs/dev/async.html\u003e`_"},{"line_number":706,"context_line":"* etc."},{"line_number":707,"context_line":""},{"line_number":708,"context_line":""},{"line_number":709,"context_line":"History"},{"line_number":710,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_f7abd572","line":707,"updated":"2015-02-16 23:29:54.000000000","message":"How would using these servers change how we recommend deploying OpenStack services today? Do they support explicit asynchronous I/O style programming, or would we be dealing with issues like we have now with eventlet due to implicit I/O context changes?","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"2743f58e8b8ab810a19fd8ea1d8c6592039d7fe5","unresolved":false,"context_lines":[{"line_number":738,"context_line":"* July 29, 2014: Doug Hellmann proposed the blueprint"},{"line_number":739,"context_line":"  `A \u0027greenio\u0027 executor for oslo.messaging"},{"line_number":740,"context_line":"  \u003chttps://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor\u003e`_,"},{"line_number":741,"context_line":"  approved by Mark McLoughlin."},{"line_number":742,"context_line":"* July 24, 2014: `Add greenio dependency \u003chttps://review.openstack.org/108637\u003e`_"},{"line_number":743,"context_line":"  merged into openstack/requirements"},{"line_number":744,"context_line":"* July 22, 2014: Patch `Add a new greenio executor"}],"source_content_type":"text/x-rst","patch_set":2,"id":"da86d52c_97ad399e","line":741,"updated":"2015-02-16 23:29:54.000000000","message":"Mark wrote the spec associated with that. I just created the blueprint record in launchpad.","commit_id":"0b29bf128ed8a710a4ba38c48c79c60a479bb989"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"68ea57f261d361025ea78aefb6db4ac460167dbb","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_740ac6d3","line":34,"updated":"2015-02-20 12:46:20.000000000","message":"Ceilometer being a guinea pig for this stuff seems reasonable enough, but given the huge amount of other work the ceilometer project needs to do to stay healthy, be performant and otherwise clean up itself I think it would be wise to attempt to limit the scope of the asyncio experiment to just one service within ceilo. Otherwise the review and testing impact will be too broad and use up already taxed resources.\n\nOne nicely contained service is the notification agent. It both consumes and produces on the message bus and because of recent changes with regard to event handling has no interaction with the database (data is sent over the bus to the collector).\n\nThis might provide a good but small domain within which to a) demonstrate the compositional capabilities of explicit async programming b) test the impact on performance.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"f15f6e7bc2c220075398609d2f4cec7a9705f2c9","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_c4abc187","line":34,"in_reply_to":"ba7be1f8_2fef1bb2","updated":"2015-02-20 13:49:42.000000000","message":"I think doing all of ceilometer as an entirely separate thing is a categorically bad idea. We\u0027re not going to change all of OpenStack in one fell swoop so we need to do a few things:\n\n* prove out the idea in a data driven (measurements) way in a contained space\n* ensure that the contained space continues to effectively interoperate with systems that have not been changed\n* define small chunks of bounded change and activity so that there are clear demarcations where we can stop and asses and adjust the plan based on what was learned\n\nKeeping things small and doing it within the standard review process will ensure that it gets as much exposure as possible to the most people.\n\nIn other words: This boil the ocean thinking that it is endemic to so much of OpenStack has got to stop. Small, incremental changes that are measured and verified are the way to move this forward with effective participation and with less risk that we\u0027ll get to the end of it and throw away a lot of effort from a lot of people.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"424a6d9412d1be6fa6e8b58891ab74889e119c3e","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_2fef1bb2","line":34,"in_reply_to":"ba7be1f8_740ac6d3","updated":"2015-02-20 13:19:59.000000000","message":"I discussed with Eoghan Glynn who told me that this spec was discussed in the Ceilometer meeting yesterday.\n\nIn the spec, I propose do the whole development in a separated branch, to not conflict with the master branch. I would prefer to defer the decision to switch ceilometer to asyncio until we have a working branch. Working means: no more eventlet at all and similar performances. So if we choose to not switch to asyncio, we don\u0027t need to revert changeset, drop dependencies, etc.\n\nThe branch may be in a complete fork. It doesn\u0027t need to be in the main repository. I don\u0027t know which option (ceilometer main repository or a fork) is the most convinient to collaborate on the project. For example, is it possible to use Gerrit on a custom branch? We may need new credentials if the git repository is hosted somewhere else (ex: github account if it\u0027s hosted at github).\n\nMehdi Abaakouk told me that he wrote a PoC to use ceilometer with asyncio a few months ago, I don\u0027t think that it was complete. But I cannot find it anymore. Maybe it was not on ceilometer, I don\u0027t remember the details...","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"763551fca13b9408057ff1b99407fdc35c8d1e0f","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_d61dfa67","line":34,"in_reply_to":"ba7be1f8_867e29e3","updated":"2015-02-23 14:02:17.000000000","message":"Mehdi Abaakouk wrote a proof-of-concept (PoC) a few months ago to run ceilometer using asyncio:\nhttps://github.com/enovance/ceilometer/tree/sileht/asyncio","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"95d16609bfa778df50ee4ee1abb090e1b4799dcc","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_867e29e3","line":34,"in_reply_to":"ba7be1f8_c4abc187","updated":"2015-02-20 15:53:30.000000000","message":"I don\u0027t think that first commits to *prepare* the code for asyncio are interesting. The benefit of asyncio will only come when all the preparation changes are made.\n\nAlso, having to wait for a review can take a lot of time. I would prefer to move fast to show working code, and then propose changes as reviews.\n\nI don\u0027t expect to have the best implementation at the first try. It may need several revisions, and it would be more convinient to work on a separated branch.\n\nIn clear: I have no idea of the number of changes that are required to switch to asyncio :-)","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"49cfa9de55f75b86da6b7a21918c3077d725767c","unresolved":false,"context_lines":[{"line_number":31,"context_line":"not be (much) slower and less reliable because of these changes. The"},{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_b39db868","line":34,"in_reply_to":"ba7be1f8_d61dfa67","updated":"2015-02-24 18:19:19.000000000","message":"I started my port to asyncio. I forked the ceilometer repository. I\u0027m working in a new asyncio branch:\nhttps://github.com/haypo/ceilometer/commits/asyncio\n\n4 commits later, ceilometer-collector runs without eventlet monkey-patching ;-)\n\nAt this point, I don\u0027t care of creating nice commits, I may rewrite some commits before sending reviews.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"d5d2d88267490d14b0d4dc2b386f58a516ca5796","unresolved":false,"context_lines":[{"line_number":32,"context_line":"development on Ceilometer may be done in a new branch of the git repository, to"},{"line_number":33,"context_line":"not touch the ``master`` branch. Then the code will then be merged with"},{"line_number":34,"context_line":"classical reviews."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Blueprint: https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Note: Since Trollius will be used, this spec is unrelated to Python 3. See the"}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_7031eb0a","line":35,"updated":"2015-02-20 15:22:04.000000000","message":"Heat uses a scheduler and coroutines using yield. It\u0027s another good candidate for asyncio:\nhttps://github.com/openstack/heat/blob/master/heat/engine/scheduler.py\n\nI already tried to rewrite Heat scheduler to reuse Trollius, but it was hard to keep exactly the same behaviour. If trollius is used, it would be easier to drop Heat scheduler and replace it with the trollius API (coroutines):\nhttps://review.openstack.org/#/c/77925/","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"68ea57f261d361025ea78aefb6db4ac460167dbb","unresolved":false,"context_lines":[{"line_number":56,"context_line":"rationale to switch from Twisted to eventlet in Nova can be found in the"},{"line_number":57,"context_line":"`eventlet vs Twisted"},{"line_number":58,"context_line":"\u003chttps://wiki.openstack.org/wiki/UnifiedServiceArchitecture#eventlet_vs_Twisted\u003e`_"},{"line_number":59,"context_line":"section of the \"Unified Service Architecture\" nova spec."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Concurrency comes with a well known but very complex issue: race conditions."},{"line_number":62,"context_line":"Let\u0027s see examples of this class of bugs: race conditions with shared states"}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_b4b51ecf","line":59,"updated":"2015-02-20 12:46:20.000000000","message":"I\u0027m nervous about these general discussions of \"we need concurrency\". They so often seem to be based in assumption or premature optimization without sure and solid basis in profiling and other real data or even solid definition of terms like \"request\".\n\nThis is especially important in a discussion where we have explicitly excluded WSGI (where concurrency problems are relatively straightforward to manage with a good server and wsgi container, some horizontal scaling, and a good persistence library) and the term \"request\" is so commonly overloaded to mean web request. If we\u0027re not in the web context what is request meaning in this problem description?","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b703daf83b86c489611a2fbf73fbb13044837f52","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Problem: using locks you get a new class of bugs, \"dead locks\". If"},{"line_number":152,"context_line":"``do_something()`` calls directly or indirectly ``create_identifier()``, the"},{"line_number":153,"context_line":"code hangs because of a dead lock: an older call to ``create_identifier()`` in"},{"line_number":154,"context_line":"the stack already hold the lock. Hopefully, reentrant calls are rare."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"The dead lock can be avoided if the lock is released before calling"},{"line_number":157,"context_line":"``do_something()``::"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_e183ae53","line":154,"updated":"2015-02-19 00:42:06.000000000","message":"Hopefully doing this kind of stuff with \u0027ids\u0027 is rare :-P","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"e6d7a2e93271c49edde5e38535c911a20f0763a0","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Problem: using locks you get a new class of bugs, \"dead locks\". If"},{"line_number":152,"context_line":"``do_something()`` calls directly or indirectly ``create_identifier()``, the"},{"line_number":153,"context_line":"code hangs because of a dead lock: an older call to ``create_identifier()`` in"},{"line_number":154,"context_line":"the stack already hold the lock. Hopefully, reentrant calls are rare."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"The dead lock can be avoided if the lock is released before calling"},{"line_number":157,"context_line":"``do_something()``::"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_04f37073","line":154,"updated":"2015-02-19 02:13:06.000000000","message":"if the code is reentrant then you use an RLock.  But also, why does do_something() need to be in create_identifier() at all?  It\u0027s being passed a unique identifier, what will it conflict with?  Why would the job of incrementing safely and do_something() be conflated like that?  If do_something() calls create_identifier() in a reentrant style, each of those calls to create_identifier() would return the *same* value of unique_id because it hasn\u0027t been incremented yet.  This code is broken without any threads getting involved.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"dc08ad8cb2256333893c80a28a1e690614c5aee1","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Problem: using locks you get a new class of bugs, \"dead locks\". If"},{"line_number":152,"context_line":"``do_something()`` calls directly or indirectly ``create_identifier()``, the"},{"line_number":153,"context_line":"code hangs because of a dead lock: an older call to ``create_identifier()`` in"},{"line_number":154,"context_line":"the stack already hold the lock. Hopefully, reentrant calls are rare."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"The dead lock can be avoided if the lock is released before calling"},{"line_number":157,"context_line":"``do_something()``::"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_64e4163c","line":154,"in_reply_to":"da86d52c_04f37073","updated":"2015-02-19 15:09:14.000000000","message":"\"But also, why does do_something() need to be in create_identifier() at all? It\u0027s being passed a unique identifier, what will it conflict with? Why would the job of incrementing safely and do_something() be conflated like that?\"\n\nI only wrote the example to demonstrate a kind of bugs. I didn\u0027t say that the code makes sense :-D\n\nMy main point is the race condition if do_something() switchs to a new thread/greenthread (ex: because an I/O operation). Again, I\u0027m not sure that it\u0027s useful to analyze an hypotetical reentrant call, since it sounds completly crazy to do that and no code should be written like that.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"4999e8e5d7eb3f647314345ff9d40c4b44bef70c","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Problem: using locks you get a new class of bugs, \"dead locks\". If"},{"line_number":152,"context_line":"``do_something()`` calls directly or indirectly ``create_identifier()``, the"},{"line_number":153,"context_line":"code hangs because of a dead lock: an older call to ``create_identifier()`` in"},{"line_number":154,"context_line":"the stack already hold the lock. Hopefully, reentrant calls are rare."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"The dead lock can be avoided if the lock is released before calling"},{"line_number":157,"context_line":"``do_something()``::"}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_8355b4fb","line":154,"in_reply_to":"da86d52c_64e4163c","updated":"2015-02-25 03:19:27.000000000","message":"I agree, but more to the point I think - most OpenStack services expect to be one-of-many, especially the API servers - id allocation etc etc is generally delegated to the DB or some other thing - global state like this race indicates is an anti-pattern in threads as well, with the rare exception being the case where we\u0027re implementing a backing service and then we\u0027d still have Paxos or Raft in play, vs a local in-process lock.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"dc08ad8cb2256333893c80a28a1e690614c5aee1","unresolved":false,"context_lines":[{"line_number":151,"context_line":"Problem: using locks you get a new class of bugs, \"dead locks\". If"},{"line_number":152,"context_line":"``do_something()`` calls directly or indirectly ``create_identifier()``, the"},{"line_number":153,"context_line":"code hangs because of a dead lock: an older call to ``create_identifier()`` in"},{"line_number":154,"context_line":"the stack already hold the lock. Hopefully, reentrant calls are rare."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"The dead lock can be avoided if the lock is released before calling"},{"line_number":157,"context_line":"``do_something()``::"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_49080b2d","line":154,"in_reply_to":"da86d52c_e183ae53","updated":"2015-02-19 15:09:14.000000000","message":"After sending the new spec, I was no more sure that it\u0027s useful to discuss this very specific corner case: create_identifier() calls do_something() between \"id \u003d self._unique_id\" and \"self._unique_id +\u003d 1\", do_something() calls again create_identifer().\n\nAs Mike noticed, even with a reentrant lock, the code is still unsafe. (I also found the issue after submiting the spec, when trying to understand what I wrote :-)) If I understand correctly, it\u0027s not possible to write safe \"reentrant\" code with threads, eventlet nor asyncio if do_something() cannot be moved. So it\u0027s not interesting to explain the same issue for each concurrency model.\n\nThe correct fix is to move the do_something() call after \"self._unique_id +\u003d 1\" (and after releasing the lock, if a lock is used), or to modify do_something() to *schedule* a call to create_identifer() (ex: eventlet.spawn() or loop.call_soon()), to break the direct dependency between do_something() and create_identifier().","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"e6d7a2e93271c49edde5e38535c911a20f0763a0","unresolved":false,"context_lines":[{"line_number":274,"context_line":"        self._unique_id +\u003d 1"},{"line_number":275,"context_line":"        # safe if called after"},{"line_number":276,"context_line":"        yield from do_something(id)"},{"line_number":277,"context_line":"        return id"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"If the call to ``do_something()`` cannot be moved, a lock is required::"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_87acc236","line":277,"updated":"2015-02-19 02:13:06.000000000","message":"is that because the \"return\" is directly after the \"yield\" and therefore the coroutine completes immediately?   that seems pretty implicit and subtle if im understanding that correctly (which I\u0027m really not sure I am).","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"dc08ad8cb2256333893c80a28a1e690614c5aee1","unresolved":false,"context_lines":[{"line_number":274,"context_line":"        self._unique_id +\u003d 1"},{"line_number":275,"context_line":"        # safe if called after"},{"line_number":276,"context_line":"        yield from do_something(id)"},{"line_number":277,"context_line":"        return id"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"If the call to ``do_something()`` cannot be moved, a lock is required::"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_64c5f65a","line":277,"in_reply_to":"da86d52c_87acc236","updated":"2015-02-19 15:09:14.000000000","message":"I don\u0027t understand your question. The effective duration of the do_something() call doesn\u0027t matter here. It can block on I/O, take several seconds, etc.\n\nIt\u0027s safe because the coroutine cannot be interrupted anymore between \"id \u003d self._unique_id\" and \"self._unique_id +\u003d 1\" instructions.\n\nUsing asyncio, you have a big hint: only lines starting with \"yield from\" can interrupt a coroutine. Otherwise, asyncio guarantee that the code between two \"yield from\" is executed sequentially.\n\nSwitch between coroutines are explicit, not implicit: you must write \"yield from\".\n\nDoes it answer to your question?","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b703daf83b86c489611a2fbf73fbb13044837f52","unresolved":false,"context_lines":[{"line_number":294,"context_line":""},{"line_number":295,"context_line":"If ``do_something()`` calls ``create_identifier()``, the code hangs because of"},{"line_number":296,"context_line":"a dead lock. asyncio does not support reentrant locks for coroutines."},{"line_number":297,"context_line":"Hopefully, reentrant calls are rare."},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"In practice, locks are not needed with asyncio is most cases. For example, *no*"},{"line_number":300,"context_line":"lock is used in the source code of asyncio."}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_41cb9aa3","line":297,"updated":"2015-02-19 00:42:06.000000000","message":"Interesting to know this.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"e6d7a2e93271c49edde5e38535c911a20f0763a0","unresolved":false,"context_lines":[{"line_number":294,"context_line":""},{"line_number":295,"context_line":"If ``do_something()`` calls ``create_identifier()``, the code hangs because of"},{"line_number":296,"context_line":"a dead lock. asyncio does not support reentrant locks for coroutines."},{"line_number":297,"context_line":"Hopefully, reentrant calls are rare."},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"In practice, locks are not needed with asyncio is most cases. For example, *no*"},{"line_number":300,"context_line":"lock is used in the source code of asyncio."}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_0709b294","line":297,"updated":"2015-02-19 02:13:06.000000000","message":"So we\u0027ve traded one set of concurrency constructs for another, plus we still have locks and all that (which we wouldn\u0027t need, just like we seldom need threading.Lock either), and a new set of subtle rules for how to use them.\n\nOpenstack already has lots of deadlock-related issues which are because we\u0027re using relational databases that lock.   A single asyncio or eventlet process can easily deadlock in this way.     We still have multiple processes which proceed non-deterministically against databases that lock, and that\u0027s where most of our concurrency issues reside.  \n\nWe have little to no explicit threading code as global, shared state in-process is not very typical for WSGI applications.  The coding problems that asyncio purports to solve aren\u0027t here demonstrated as problems Openstack has to any significant degree.  The examples here would make for a much better argument if they were based on actual Openstack code that is demonstrably broken right now with threads, or runs on eventlet and would be very difficult to make correct with threads.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"dc08ad8cb2256333893c80a28a1e690614c5aee1","unresolved":false,"context_lines":[{"line_number":294,"context_line":""},{"line_number":295,"context_line":"If ``do_something()`` calls ``create_identifier()``, the code hangs because of"},{"line_number":296,"context_line":"a dead lock. asyncio does not support reentrant locks for coroutines."},{"line_number":297,"context_line":"Hopefully, reentrant calls are rare."},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"In practice, locks are not needed with asyncio is most cases. For example, *no*"},{"line_number":300,"context_line":"lock is used in the source code of asyncio."}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_f8ed0a26","line":297,"in_reply_to":"da86d52c_0709b294","updated":"2015-02-19 15:09:14.000000000","message":"\u003e So we\u0027ve traded one set of concurrency constructs for another, plus we still have locks and all that (which we wouldn\u0027t need, just like we seldom need threading.Lock either), and a new set of subtle rules for how to use them.\n\nI\u0027m saying the opposite in the spec. Basically, with threads you always need locks, except of a few simple cases. With asyncio, you almost never need locks. Locks are complex. Without locks, no risk of dead lock :-) So I don\u0027t understand your analysis.\n\n\u003e Openstack already has lots of deadlock-related issues which are because we\u0027re using relational databases that lock. A single asyncio or eventlet process can easily deadlock in this way.\n\nYou already used this argument, but I don\u0027t get it. In this spec, I compare different concurreny models: threads, eventlet, asyncio. None of these models avoid dead locks if the lock is outside the process. So what\u0027s the point?\n\nIn the introduction, I also added the note \"Changing how concurrency is handled inside a process has no impact on parallelism using multiple processes.\" to explain that I wil not discuss issue of distributed systems in the spec.\n\n\u003e We have little to no explicit threading code as global, shared state in-process is not very typical for WSGI applications. The coding problems that asyncio purports to solve aren\u0027t here demonstrated as problems Openstack has to any significant degree. The examples here would make for a much better argument if they were based on actual Openstack code that is demonstrably broken right now with threads, or runs on eventlet and would be very difficult to make correct with threads.\n\nI used a dummy example to explain the issue, but I agree that it\u0027s artificial.\n\nOk, I will try to find more concrete examples in existing OpenStack source code. I don\u0027t think that I will be able to find code with race conditions which impact eventlet, since OpenStack is used in production with eventlet. I expect to find more race conditions which impact threads (ex: objects shared between threads without lock).\n\nBy the way, the problem is wider than \"OpenStack\": unfortunately, race conditions can also occur in external libraries and OpenStack uses a ton of external libraries :-( I bet that many libraries are not thread-safe. It\u0027s not an issue today because we use monkey-patching and greenthreads. I fear more race conditions if we replace eventlet with threads, for the reasons explained in the \"Threads\" section above.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"4999e8e5d7eb3f647314345ff9d40c4b44bef70c","unresolved":false,"context_lines":[{"line_number":294,"context_line":""},{"line_number":295,"context_line":"If ``do_something()`` calls ``create_identifier()``, the code hangs because of"},{"line_number":296,"context_line":"a dead lock. asyncio does not support reentrant locks for coroutines."},{"line_number":297,"context_line":"Hopefully, reentrant calls are rare."},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"In practice, locks are not needed with asyncio is most cases. For example, *no*"},{"line_number":300,"context_line":"lock is used in the source code of asyncio."}],"source_content_type":"text/x-rst","patch_set":3,"id":"ba7be1f8_c3c5ec8e","line":297,"in_reply_to":"da86d52c_4742af3e","updated":"2015-02-25 03:19:27.000000000","message":"I agree - the assertion that we\u0027d need locks in threaded code presupposes a lot about the nature of the things we need to do in our threaded code. It\u0027s easy to imagine situations where we have long (seconds) interactions with external resources where locking would be needed - but it would also be needed for both asyncio and eventlet as we would want to not block, and without blocking concurrency will occur.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"47e3eff37b2864cfbf795280894258a1662e9c74","unresolved":false,"context_lines":[{"line_number":294,"context_line":""},{"line_number":295,"context_line":"If ``do_something()`` calls ``create_identifier()``, the code hangs because of"},{"line_number":296,"context_line":"a dead lock. asyncio does not support reentrant locks for coroutines."},{"line_number":297,"context_line":"Hopefully, reentrant calls are rare."},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"In practice, locks are not needed with asyncio is most cases. For example, *no*"},{"line_number":300,"context_line":"lock is used in the source code of asyncio."}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_4742af3e","line":297,"in_reply_to":"da86d52c_f8ed0a26","updated":"2015-02-19 16:28:30.000000000","message":"\u003e with threads you always need locks, except of a few simple cases. \n\nwe\u0027re going in circles.    \"with threads you always need locks\".   Where?  Are these locks that Openstack programmers care about ?   How much use of threading.Lock() is actually in Openstack code?    \"you always need locks\" is like saying \"you always need a CPU\".    Where are these locks, are they anywhere that they we care about as day-to-day openstack programmers ?  Or are they totally part of existing libraries that we never have to worry about, and even then, a minimal aspect of most libraries?\n\n\u003e Without locks, no risk of dead lock :-)\n\nexcept this very spec shows how to get a deadlock with asyncio and no locks.   \n\n\u003e None of these models avoid dead locks if the lock is outside the process. So what\u0027s the point?\n\nthe point is, asyncio vs. threads doesn\u0027t save us anything as far as the concurrency related issues openstack faces.   \n\n\u003e I bet that many libraries are not thread-safe.\n\nI think you should look into that and you might be surprised.  I\u0027m not sure where your anxiety about threading comes from.  If it only comes from blog posts, then that\u0027s not sufficient; those posts IMO are not very realistic or practical.   I\u0027ve written tons of thread safe code over the course of 20 years, it can be done.   If you\u0027re trying to do something fancy, then yes you can get yourself into trouble, which I also have done, but  within Openstack, we also have a review process; people like me can come in and ensure that the code is OK.    The GIL actually helps to a large extent here; \"thread unsafe code\" in Python is way simpler to understand than the kinds of races you\u0027d get in C code for example.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b703daf83b86c489611a2fbf73fbb13044837f52","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_c1e94ae4","line":318,"updated":"2015-02-19 00:42:06.000000000","message":"Its also a nice opportunity to review all libraries that everyone uses to.... It\u0027s gonna be a lot of reviews..\n\nI sort of feel that asyncio seems to bring us back to having to manually specify yield points; which I sorta feel is move backwards, not a move forwards in terms of progress. Computers seem somewhat good at scheduling things, and having to manually specify yield points turns me into a scheduler, which I\u0027m not so good at, haha.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b703daf83b86c489611a2fbf73fbb13044837f52","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_e1380ea2","line":318,"updated":"2015-02-19 00:42:06.000000000","message":"Sure, and I get this, but we also have computers to let us developers get away from manually specifying when to schedule things.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"e6d7a2e93271c49edde5e38535c911a20f0763a0","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_47364a52","line":318,"updated":"2015-02-19 02:13:06.000000000","message":"The criticism to this point is that we\u0027d end up with \"yield from\" all over the place, it will be so ubiquitous that it would be meaningless.   With explicit async we\u0027re essentially attempting to implement the scheduling of the program manually, except this job is interfered with by the fact that the architecture of this scheduling cannot be separated from when we happen to need to do network IO.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":9107,"name":"Victor Stinner","email":"vstinner@redhat.com","username":"haypo"},"change_message_id":"dc08ad8cb2256333893c80a28a1e690614c5aee1","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_f8cb4a1b","line":318,"in_reply_to":"da86d52c_0d9d4cbc","updated":"2015-02-19 15:09:14.000000000","message":"\u003e Its also a nice opportunity to review all libraries that everyone uses to.... It\u0027s gonna be a lot of reviews..\n\nHum, I don\u0027t understand. Can you please elaborate? When would you have to review external libraries?\n\n\u003e I sort of feel that asyncio seems to bring us back to having to manually specify yield points; which I sorta feel is move backwards, not a move forwards in terms of progress.\n\nExactly, asyncio is based on explicit asynchronous programming, you explicitly say when you switch to a new coroutine using \"yield from\".\n\nIMO it makes programming simpler and safer. I don\u0027t know how to convince you, maybe I can\u0027t :-)\n\n\u003e Computers seem somewhat good at scheduling things, and having to manually specify yield points turns me into a scheduler, which I\u0027m not so good at, haha.\n\nYou don\u0027t schedule tasks yourself. You have to say when you want to wait for wait for an asynchronous operation, so the asyncio scheduler can run execute pending tasks until the operation completed. It\u0027s different.\n\nYou don\u0027t *have to* yield control to other task, you can keep the CPU for you. Only do it when appropriate (ex: only when you interact with a socket). In an application, they are few places where you interact with a socket. I hope that your application has few lines between \"sock.recv\" and \"sock2.send\" ;-)\n\n\u003e The criticism to this point is that we\u0027d end up with \"yield from\" all over the place\n\nI replied to that in the \"No need to rewrite completly OpenStack\" section below.\n\n\u003e why didn\u0027t [python] just make this \u0027yield from\u0027 a comment or why didn\u0027t python just adopt (and embrace) greenlet(s) \n\nI found an explication in a Pycon 2014 keynote by Guido van Rossum who explains the rationale of asyncio:\nhttp://lwn.net/Articles/544522/\n\n\"Advocates of gevent would claim that it solves all those problems, but \"somehow it doesn\u0027t do it\" for him. There are some \"scary implementation details\", including CPython- and x86-specific code. It does some \"monkey patching\" of the standard library to make it \"sort of work\". It also does not avoid the problem of knowing where the scheduler can switch tasks. There is a specific call that gets made to cause task switches to happen, but you never know when that may be called. Some library function could be making that call (or may in the future), for example. It essentially is the same situation as with OS threads. Beyond switching at unexpected times, there is also the problem of not switching enough, which can cause some tasks to be CPU starved. He \"can\u0027t help\" wanting to know if a particular line of code could end up suspending the current task.\"\n\nIn short: explicit async is a strong design choice, to solve real issues.","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"f0c6f6e14eea85b65cf8c424d3dfc02545f0dfce","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_0d9d4cbc","line":318,"in_reply_to":"da86d52c_47364a52","updated":"2015-02-19 07:06:43.000000000","message":"Ya, I don\u0027t like being a scheduler, lol; IMHO this sort of goes back to michaels blogs post question about why didn\u0027t they just make this \u0027yield from\u0027 a comment or why didn\u0027t python just adopt (and embrace) greenlet(s) (and say have a interpreter option that would use greenthreads vs real-threads *transparently*)?? Since in the worst case u are placing \u0027yield from\u0027 on every line of code (especially in I/O heavy applications) and at that point it makes u wonder what the heck is going on with python as a language....","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"94e180e69de9468f65990dfd4b3b232d6f8dd4e4","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_4d5664cf","line":318,"in_reply_to":"da86d52c_e1380ea2","updated":"2015-02-19 07:08:18.000000000","message":"Odd, guess I double posted with nearly equivalent comments; my fault :-/","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"80e3f8d1de813f36d4f46ccdbd3599f56bdd803c","unresolved":false,"context_lines":[{"line_number":315,"context_line":"``do_something()`` cannot \"silently\" become asynchronous. If ``do_something()``"},{"line_number":316,"context_line":"becomes a coroutine, all callers of the function (coroutine) must be modified."},{"line_number":317,"context_line":"The modification is a nice opportunity to review carefully the code around the"},{"line_number":318,"context_line":"call to check for race conditions."},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"The race condition may be missed during in the review, but the difference"},{"line_number":321,"context_line":"between eventlet and asyncio is that you don\u0027t have this opportunity with"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_06035442","line":318,"in_reply_to":"da86d52c_f8cb4a1b","updated":"2015-02-19 18:26:14.000000000","message":"\u003e You don\u0027t *have to* yield control to other task, you can keep the CPU for you. Only do it when appropriate (ex: only when you interact with a socket). In an application, they are few places where you interact with a socket. I hope that your application has few lines between \"sock.recv\" and \"sock2.send\" ;-)\n\nThis may be the case for some applications but let us use an example of libraries that do interact with networks (sqlalchemy for example). Wouldn\u0027t those libraries have to scatter \u0027yield from\u0027 at many points because in order to make a library that doesn\u0027t just \u0027block\u0027 all the time it would need to yield at every possible point where some socket/network activity could happen. This turns the library creator(s) code into a large degree of noise (IMHO), because at every call into some network/socket using library (for example, assume sqlalchemy calls into mysql-connector or postgresql... to do most of the work, which afaik it does) sqlachemy must then yield from every call point into that underlying library (because who knows that underlying library may do some socket activity....).\n\nThis IMHO means libraries that are providing *useful* abstractions over other network/socket/io using libraries (sqlalchemy, tooz, ...) now are that more complicated, and for what benefit?","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"b703daf83b86c489611a2fbf73fbb13044837f52","unresolved":false,"context_lines":[{"line_number":523,"context_line":"OpenStack has a long list of third-party libraries. Since asyncio is young,"},{"line_number":524,"context_line":"only few libraries have a native asyncio support. asyncio will probably become"},{"line_number":525,"context_line":"the defacto API for asynchronous programming in the future, because it is part"},{"line_number":526,"context_line":"of the Python standard library. We can expect more and more libraries"},{"line_number":527,"context_line":"supporting asyncio. For example, SQLAlchemy plans to support asyncio."},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"What should be done with libraries which don\u0027t know anything about asyncio?"}],"source_content_type":"text/x-rst","patch_set":3,"id":"da86d52c_64698cbd","line":526,"updated":"2015-02-19 00:42:06.000000000","message":"Or people will move to go/other new hot language due to the python communities continuous change the world behavior (python2-\u003epython3, now asnycio...) My vote is out on what will actually happen still... Hope for the best but it does make me wonder....","commit_id":"9067443cc73f853beb222bb3de8115c3920d29b4"}]}
