Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt async runtime #172

Open
rnbguy opened this issue Oct 19, 2022 · 0 comments
Open

Adopt async runtime #172

rnbguy opened this issue Oct 19, 2022 · 0 comments
Labels
dev Changes that make development easier: refactoring, tooling etc.

Comments

@rnbguy
Copy link
Member

rnbguy commented Oct 19, 2022

Async runtime provides a friendlier interface to handle concurrent tasks. Python's asyncio library reduces the code burden and offers more straightforward methods. The main cost is tagging methods with async or await accordingly.

Asyncio vs Multiprocess vs Threads

First, let us go through its comparison with other options to evaluate it properly. This blog post discusses the ideal case scenarios among these options. I roughly listed them in the following table.

Process Threads I/O CPU
Async few few slow -
Thread single multi fast -
Multiprocess multi multi - heavy

This StackOverflow reply may also be worth reading.

Atomkraft works with few processes and slow I/O tasks. There is no thread involved and no extensive computations while Atomkraft runs. It mainly,

  • Setups a distributed system - spawning binary processes.
  • Orchestrates the test - communicating with remote servers (over RPC, GRPC, REST, etc.), which are de-facto async use cases.

Leading example

Consider the following sample code.

import asyncio


async def run_test():
    await asyncio.sleep(10)
    raise RuntimeError


async def run_node(i: int):
    await asyncio.sleep(i)
    if i == 5:
        raise RuntimeError(f"node error: id {i}")
    await asyncio.sleep(i)


async def runtime(n_node: int):
    try:
        await asyncio.gather(*[run_node(i + 1) for i in range(n_node)], run_test())
    except RuntimeError as e:
        print(e)
    print("all good")


if __name__ == "__main__":
    asyncio.run(runtime(6))

The only concise way to rewrite the above would be using .apply_async() or ProcessPoolExecutor, which has more code complexity in my opinion. I don't know any other way to rewrite the same concisely in blocking runtime.

Few ways Atomkraft can benefit

Rough plan of Async migration

  • Adopt pytest-asyncio
  • Support Async reactors along with blocking reactors
  • Modify Atomkraft's pytest plugin to work with async procedures
@rnbguy rnbguy added the enhancement New feature or request label Oct 19, 2022
@ivan-gavran ivan-gavran added dev Changes that make development easier: refactoring, tooling etc. and removed enhancement New feature or request labels Nov 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev Changes that make development easier: refactoring, tooling etc.
Projects
None yet
Development

No branches or pull requests

2 participants