2014-07-23 71 views
4

就在我寫更多core.async碼,即出現一個很常見的模式就是去環,超過通道序列低價競標,並不會響應某些工作提高到一個消息,例如:什麼是在clojure core.async go-loop中工作的方式的權衡?

(go-loop [state {}] 
    (let [[value task] (alts! tasks)] 
    ...work... 
    (recur state)) 

我不我覺得我理解我可以通過各種方式實際完成工作的權衡,所以我想我會試着在這裏探索它們。

  • 內嵌或通過調用函數:這將阻止循環繼續,直到工作完成。由於它在一個go塊中,所以不想進行I/O或鎖定操作。
  • >!向工作人員監控的通道發送一條消息:如果通道已滿,則通過停車直到通道有容量來阻止迴路。這允許螺紋做其他工作並且允許背壓。
  • > !!一條消息:如果通道已滿,則通過睡眠執行go循環的線程來阻塞。這可能是不受歡迎的,因爲執行線程是一個嚴格有限的資源。
  • >!在另一個go塊中的消息:除非沒有可用的線程,否則這將幾乎立即成功。相反,如果頻道已滿並且正在慢慢消耗,這可能會短時間內使線程系統癱瘓。
  • > !!帶有線程塊​​的消息:類似於go塊,但是消耗系統線程而不是線程,因此上限可能更高
  • puts!一條消息:目前尚不清楚什麼是權衡
  • 將來會調用工作函數:將工作交給clojure代理池中的一個線程來執行,允許go循環繼續。如果輸入速率超過輸出速率,則會增加代理緩衝池隊列的無限制。

此內容摘要是否正確而全面?

回答

4

如果要完成的工作完全受CPU限制,那麼我可能會在go塊中內聯它,除非它是需要很長時間的操作並且我希望go塊繼續響應其他消息。一般來說,任何不阻塞,休眠或I/O的工作都可以安全地放入go塊中,而不會對系統的吞吐量產生重大影響。

您可以使用>!將作品提交給工人或工作人員。我幾乎不會在go塊中使用>!!,因爲它可以阻塞分配給運行go塊的有限數量的線程之一。

當您需要執行I/O或可能長時間運行的計算時,請使用thread而不是go。這與future非常相似 - 它創建了一個真實的線索 - 但它返回了一個像go這樣的頻道。

put!是一個較低級別的操作,通常用於core.async的「邊界」以將其連接到傳統的基於回調的接口。在go內部很少有任何理由使用put!

core.async可以支持對線程創建的細粒度控制。我在博客文章Parallel Processing with core.async中展示了一些可能性。

相關問題