2016-06-24 50 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