繁体   English   中英

从 python 中的命名 pipe 读取时的 CPU 使用率/速度权衡

[英]CPU usage/ speed tradeoff when reading from a named pipe in python

我想在 python 中异步读取 pipe。 pipe 从另一个进程(javascript 进程)连续进料。 我使用管道是为了速度。

我不想循环查看文件是否附加了新行,因为它占用了 100% 的 CPU。 我试过watchgod awatch ,但它增加了 300 毫秒的延迟。 我的权衡是 1ms 的asyncio.sleep ,它占用了 10% 的 CPU,但增加了 1ms 的延迟。

import json
import time

import aiofiles
# from watchgod import awatch


async def amain():
    async with aiofiles.open('pipe_a', mode='r') as f:
        # async for changes in awatch('pipe_a'): # CPU=0% TIME=300ms
        while True:
            async for line in f:
                x = json.loads(line)
                print(f"pong: {time.time() * 1000 - x['time']} ms")
            await asyncio.sleep(0.001) # # CPU=10% TIME=1.5ms
            # await asyncio.sleep(0) # # CPU=100% TIME=0.5ms


import asyncio

loop = asyncio.get_event_loop()

loop.run_until_complete(amain())

什么是获得 0.5ms 延迟和 0% CPU 使用率的正确方法?

Watchgod awatch本身正在执行异步循环。 这就是为什么它需要 300 毫秒,因为默认循环的延迟是 300 毫秒。

在 Linux 上,要查看文件更改,必须使用inotify python 上有一个用于 inotify 的异步库: aionotify 使用 notify 等待文件更改不会阻塞 CPU 并会在文件事件出现时立即捕获它。

该解决方案占用 0% 的 CPU 使用率和 0.5 毫秒的延迟:

import asyncio
import aiofiles
import aionotify
import json
import time

watcher = aionotify.Watcher()
watcher.watch(alias='logs', path='pipe_a', flags=aionotify.Flags.MODIFY)

# Prepare the loop
loop = asyncio.get_event_loop()


async def amain():
    await watcher.setup(loop)
    async with aiofiles.open('pipe_a', mode='r') as f:
        try:
            while True:
                _ = await watcher.get_event()
                async for line in f:
                    x = json.loads(line)
                    print(f"pong: {time.time() * 1000 - x['time']} ms")
        finally:
            watcher.close()


loop.run_until_complete(amain())
loop.stop()
loop.close()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM