2016-06-24 54 views
2

将一些代码转换为使用asyncio,我想尽快地控制asyncio.BaseEventLoop。这意味着要避免阻止等待。asyncio如何安排文件系统统计操作?

没有asyncio我会用os.stat()pathlib.Path.stat()来获得例如。文件大小。有没有一种方法可以有效地用asyncio做到这一点?

我可以直接打包stat()电话,因此它是类似于described here的未来吗?

+0

你的意思是:你想要一个非阻塞的'os.stat()',这样其他协程可以在其中运行吗? –

+0

@Julien:是的,我认为是的;-)为了让主代码并行运行,我将被迫使用线程而不是asyncio,对吗? – cfi

回答

2

os.stat()转化为一个系统调用stat

$ strace python3 -c 'import os; os.stat("/")' 
[...] 
stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 
[...] 

被拦截,而且也没有办法让一个无阻塞stat系统调用。

asyncio提供无阻塞通过使用非阻断系统调用,这已经存在的I/O(参见man fcntl,以其O_NONBLOCK标志,或ioctl),所以asyncio不使系统调用异步的,它暴露在已经异步系统调用一个不错的方法。

仍然可以使用漂亮的ThreadPoolExecutor抽象来使用线程池并行阻止stat调用。

但是你可以先考虑一些其他参数:

  • strace -Tstat快:stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 <0.000007>,可能快于启动和同步线程。
  • stat可能是在很多情况下IO的约束,因此,使用多个CPU不会帮助
  • 做并行I/O可以打破随机访问一个很好的顺序访问,物理性硬盘驱动器可能是在这种情况下慢。

但是你的stat的使用线程池的可能性也很大,就像你打到分布式文件系统一样。

您也可以查看functools.lru_cache:如果您在同一个文件或目录中执行多个stat,并且您确定它没有更改,缓存结果可避免系统调用。

总之,“保持简单”,“os.stat”是获取文件大小的有效方式。

+0

感谢您对这件事的良好想法和观察!我很害怕(或希望?)。我有可能数以百万计的统计数据,我的确不想并行化这些数据(文件系统是一个高度并行化的NAS,但在一个nfs装载上)这个想法是排队/汇集统计数据,但是能够执行基于python的其他簿记并行,以便即使在统计之后也不要等待代码执行。缓存统计信息是不行的,因为它是用于检查文件系统差异的工具(与rsync或zfs的擦除机制相比)。 – cfi

+0

现在我将保留它们的属性。后来我可以比较推动他们进入一个单独的线程,通过队列与主线程进行通信。只要将统计数据与其他代码结合使用,情况可能会更快。再次感谢! – cfi