主要問題可參考這個 issue,裡面有以下片段:
1 | import concurrent.futures as cf |
可發現這是照著文件例子寫的,只是數量增加一下,記憶體就爆了。問題乍看出在 future_to_element
長太大,但就算不把 submit()
的結果放在容器中,只要在 with clause 中就一樣會佔用記憶體。也就是說在工作數量大的情況下,ThreadPoolExecutor
並不實用。Issue 中建議是另外加個 loop 把總工作切成一批批的處理,每次處理一批就要等到全部跑完,然後換下一批。若為了節省時間把批次處理量加大,記憶體又消耗很多,不是很理想。
這其實是不必要的:future
可用以得知是否出錯、以及工作完成的結果,但要知道結果有其他機制可以利用,最典型的例如送到 queue
,問題就只剩錯誤處理。先前在「出錯就盡快停止」的條件下,寫過類似下面的程式片段:
1 | import threading |
如此不用批次也沒有消耗記憶體問題。
但以上提的還算是表面。最終是會需要 Scala concurrent.Map 那樣的機制,而且必須是 lazy,或是 Go 用 channel 也能處理得很漂亮。只能說 Python 在 concurrency 領域還差得很遠,這也限制了它作為 backend, infrastructure 等等應用的普及度。