2009-02-24 135 views
2

我正在學習C#異步套接字編程,並且我已經瞭解到在某種池中重用字節緩衝區是一個好主意,然後在從套接字接收數據時根據需要檢查一次。一個大的字節緩衝區或幾個小的緩衝區?

但是,我已經看到了兩種不同的字節數組池的使用方法:一種使用簡單的隊列系統,並根據需要將其從隊列中添加/刪除。如果請求了一個,並且隊列中沒有剩餘,則會創建一個新的字節數組。

我見過的另一種方法是在整個程序中使用一個大字節數組。隊列的思想仍然適用,但它是一個確定要使用的字節數組的片段(偏移量)的整數隊列。如果有人被請求並且隊列中沒有更多信息,則必須調整數組的大小。

其中哪一個是高度可擴展的服務器的更好解決方案?我的直覺是,使用許多字節數組會更便宜,因爲我可以想象根據需要調整數組的大小(即使我們將它分成大塊)會非常昂貴,特別是當它變大時。使用多個陣列看起來更直觀 - 使用一個我沒有想到的巨型陣列有什麼優勢?

回答

5

你的直覺是正確的。每當你需要增大數組時,你將重新創建數組並複製現有的字節。由於我們在這裏討論的是字節,數組的大小可能會很快變大。所以,每次你都會要求一段連續的內存,這取決於你的程序如何使用內存,可能或不可行。這也將實際上成爲一個虛擬池,可以這麼說。根據定義,池具有一組由多個客戶管理和共享的項目。

一個陣列解決方案的實現方式也更加複雜。好的是,一個數組的解決方案允許你給出可變大小的塊,但這是以實質上重新實現malloc爲代價的:處理碎片等,這是你不應該考慮的。

多數組解決方案允許您使用N個緩衝區初始化一個池,並以簡單的方式輕鬆管理它們。絕對是我推薦的方法。

2

我不會建議調整大小選項。從簡單開始,繼續前進。一個字節緩衝區的隊列在耗盡時添加一個新的字節緩衝區將是一個好的開始。您可能不得不關注線程問題,所以我的建議是使用別人的線程安全隊列實現。

接下來,您可以看看更復雜的「指針」到一個大的字節數組塊中,除非我的建議是有一個4k/16k的隊列(某些功率是頁面大小的兩倍)你索引進入,當它滿了時,你會向隊列中添加另一個大塊。實際上,由於性能的複雜性和可疑的收益,我不推薦這樣做。

開始簡單,工作你的方式。緩衝池,使其線程安全,看看你是否需要更多。

2

對多個緩衝區還有一票投票,但除此之外,由於您正在異步執行任務,因此您需要確保您的隊列是線程安全的。默認Queue<T>集合絕對是而不是線程安全。

SO用戶和MS員工JaredPar在這裏有一個很好的線程隊列實現:
http://blogs.msdn.com/jaredpar/archive/2009/02/16/a-more-usable-thread-safe-collection.aspx

+0

良好的調用,必須警告不要做像「if(queue.Count> 0){... dequeue ...}」這樣的事情。 – user7116 2009-02-24 14:53:07

1

如果你使用你需要的在需要的時候應該如何快速成長策略單一的緩衝區。如果你以小增量增長它,你可能需要經常做並經常複製所有數據。如果你以大增量增長它(如下一個大小是前一個大小的1.5倍),那麼當你嘗試增長緩衝區時出現「內存不足」的風險將面臨一種情況。對於可擴展系統來說,這是一個雙輸的選擇。這就是爲什麼重複使用小緩衝區是可取的。

1

對於垃圾回收堆,您應該始終使用壽命短的小型,正確大小的緩衝區。 .NET堆分配器很快,,代#0集合非常便宜。

當你保留一個靜態緩衝區時,你會在程序生命週期中耗盡系統資源。最糟糕的情況是,當它變得足夠大以至於移動到大對象堆中時,它將成爲無法移動的永久障礙。