mac os中O峎unblock fifo上的大写操作性能较差

2024-05-29 04:10:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我在FIFO上有读写器,读卡器不能无限期阻塞。为此,我用O_NONBLOCK打开read end。在

写入端可能会阻塞,因此我将其作为常规文件打开。大的写操作执行得不可接受,非常糟糕-读/写4MB块需要几分钟,而不是预期的几秒钟(这是预期的,因为在linux中相同的代码只需几秒钟)。在

在Python中复制问题的示例代码。首先,使用mkfifo创建一个fifo,例如mkfifo some_fifo,然后运行读取端,然后运行写入端。在

阅读结束:

import os, time
# mkfifo some_fifo before starting python
fd = os.open('some_fifo',os.O_RDONLY | os.O_NONBLOCK)
while True:
    try:
        read = len(os.read(fd, 8192)) # read up to 8kb (FIFO buffer size in mac os)
        print(read)
        should_block = read < 8192 # linux
    except BlockingIOError:
        should_block = True # mac os
    if should_block:
        print('blocking')
        time.sleep(0.5)

写入结束:

^{pr2}$

注意:我在这个问题上碰到的原始代码是跨平台的Java代码,它也运行在linux上。不幸的是,这意味着我不能将kqueue与kevent的data字段一起使用来计算在不阻塞的情况下我可以读取多少数据—这些数据在我使用的epoll/kqueue抽象中丢失了。这意味着使用阻塞fd à la this answer的解决方案是不可接受的。在

编辑:原始代码在读取端使用kqueue来阻塞文件描述符,这会使更糟

edit2:Linuxos.read()在连接管道的另一端之前不会抛出BlockingIOError,尽管文档声明应该这样做(调用成功(返回0),但将errno设置为EAGAIN)。更新了代码,以便对linux行为也很友好。在

编辑3:macOS的代码最初是: 在

^{3}$

这与sleeps版本的性能一样差,但是sleep可以确保问题不出在阻塞机制上,而且是跨平台的。在


Tags: 文件代码readoslinuxsomeblockfifo

热门问题