Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 异步IO的性能_Python_Python Asyncio - Fatal编程技术网

Python 异步IO的性能

Python 异步IO的性能,python,python-asyncio,Python,Python Asyncio,我试图熟悉asyncio,所以我决定编写一个数据库客户机。但是,性能与同步代码完全匹配。我相信这是我对一个概念的误解。有人能解释一下我在干什么吗 请参阅下面的代码示例: class Connection: def __init__(self, reader, writer, loop): self.futures = deque() # ... self.reader_task = asyncio.async(self.recv_dat

我试图熟悉asyncio,所以我决定编写一个数据库客户机。但是,性能与同步代码完全匹配。我相信这是我对一个概念的误解。有人能解释一下我在干什么吗

请参阅下面的代码示例:

class Connection:
    def __init__(self, reader, writer, loop):
        self.futures = deque()

        # ...

        self.reader_task = asyncio.async(self.recv_data(), loop=self.loop)

    @asyncio.coroutine
    def recv_data(self):
        while 1:
            try:
                response = yield from self.reader.readexactly(4)
                size, = struct.unpack('I', response)
                response = yield from self.reader.readexactly(size)

                # ...                

                future = self.futures.popleft()

                if not future.cancelled():
                    future.set_result(response)

            except Exception:
                break

    def send_data(self, data):
        future = asyncio.Future(loop=self.loop)
        self.futures.append(future)

        self.writer.write(data)

        return future


loop = asyncio.get_event_loop()


@asyncio.coroutine
def benchmark():
    connection = yield from create_connection(loop=loop, ...)

    for i in range(10000):
        yield from connection.send_data(...)


s = time.monotonic()

loop.run_until_complete(benchmark())

e = time.monotonic()
print('Requests per second:', int(10000 / (e - s)))
提前感谢。

python模块是单线程的:

该模块提供了使用协程编写单线程并发代码、通过套接字和其他资源多路复用I/O访问、运行网络客户端和服务器以及其他相关原语的基础结构

解释了为什么asyncio可能比线程化慢,但简而言之:asyncio使用一个线程来执行代码,所以即使您有多个协程,它们都是串行执行的。线程池用于执行一些回调和I/O。由于GIL,线程也可以串行执行用户代码,尽管I/O操作可以同步运行


与串行执行的代码相比,使用asyncio并没有给您带来改进的原因是,事件循环一次只运行一个协程。

您在调用
send\u data
时犯了一个错误。现在,你有了这个:

@asyncio.coroutine
def benchmark():
    connection = yield from create_connection(loop=loop, ...)

    for i in range(10000):
        yield from connection.send_data(...)
通过在for循环中使用
yield from
,您正在等待
将来的
send_data
返回的结果,然后再进行下一次调用。这使您的程序基本上是同步的。您想对
send_data
进行所有调用,然后等待结果:

@asyncio.coroutine
def benchmark():
    connection = yield from create_connection(loop=loop, ...)
    yield from asyncio.wait([connection.send_data(..) for _ in range(10000)])

OPs代码的性能仍应优于同步代码,因为它受I/O限制。有一个线程并不重要——当I/O在一个协程中运行时,其他协程可以执行。您链接到的问题有点特殊-它使用的是
getaddrinfo
,实际上并不是使用异步I/O实现的。它使用一个小的
线程池
,这限制了可用的并行量。这使得它比常规的多线程代码慢,但它仍然比同步代码快,这就是这个问题的核心所在。@dano我错了。我不太明白。我对你的答案投赞成票,没问题。异步框架是一个相当奇怪的概念。你在回答中写的最后一句话实际上基本上是正确的,但这是因为编码错误,而不是
asyncio
的限制。太好了,谢谢。从我的理解来看,这与为每个“发送数据”调用创建一个任务是一样的?@Andrew或多或少,尽管您仍然需要向
基准测试添加代码,以等待每个
任务完成。实际上,我相信对
asyncio.wait
的调用会将传递给它的所有协同程序对象在内部转换为
Task
实例。是的,你们都是对的
asyncio.wait
将在
任务
中包装任何传入的协同路由对象或可等待的对象。用
循环自己包装它们的单独行为。创建\u task
asyncio。确保\u future
可以在循环中调度它们,但在它们最终完成时不会阻止协同程序代码的执行。您仍然必须从这些
任务中
屈服,或者将它们传递给类似
asyncio.wait的东西。