我正在试验 mit 命名管道和 async
方法,有点惊讶,我创建的文件的读取速度似乎很慢。
正如this question所暗示的那样,这种效果不仅限于下面示例中的命名管道,还适用于“普通”文件。由于我的最终目标是阅读那些命名管道,因此我更愿意保留下面的示例。
所以这是我最初想出的:
import sys, os
from asyncio import create_subprocess_exec, gather, run
from asyncio.subprocess import DEVNULL
from aiofile import async_open
async def read_strace(namedpipe):
with open("async.log", "w") as outfp:
async with async_open(namedpipe, "r") as npfp:
async for line in npfp:
outfp.write(line)
async def main(cmd):
try:
myfifo = os.mkfifo('myfifo', 0o600)
process = await create_subprocess_exec(
"strace", "-o", "myfifo", *cmd,
stdout=DEVNULL, stderr=DEVNULL)
await gather(read_strace("myfifo"), process.wait())
finally:
os.unlink("myfifo")
run(main(sys.argv[1:]))
您可以像 ./sync_program.py <CMD>
一样运行它,例如./sync_program.py find .
这个使用默认 Popen
并读取 strace
写入 myfifo
的内容:
from subprocess import Popen, DEVNULL
import sys, os
def read_strace(namedpipe):
with open("sync.log", "w") as outfp:
with open(namedpipe, "r") as npfp:
for line in npfp:
outfp.write(line)
def main(cmd):
try:
myfifo = os.mkfifo('myfifo', 0o600)
process = Popen(
["strace", "-o", "myfifo", *cmd],
stdout=DEVNULL, stderr=DEVNULL)
read_strace("myfifo"),
finally:
os.unlink("myfifo")
main(sys.argv[1:])
用 time
运行两个程序表明异步程序慢了大约 15 倍:
$ time ./async_program.py find .
poetry run ./async_program.py find . 4.06s user 4.75s system 100% cpu 8.727 total
$ time ./sync_program.py find .
poetry run ./sync_program.py find . 0.27s user 0.07s system 76% cpu 0.438 total
链接的问题表明 aiofile
以某种方式缓慢,但 15 倍?我很确定我仍然通过使用额外的线程并写入队列来接近同步方法,但不可否认我还没有尝试过。
是否有推荐的异步读取文件的方法——甚至可能是一种更专用于命名管道的方法,因为我在给定的示例中使用了命名管道?