2012-10-03 57 views
2

在我們的應用程序中,我們有一個產生字符的類,另一個消耗它們。當前的實現動態分配字符(使用new),並在消耗時刪除它們(使用delete)。這一切都非常緩慢,我正在尋找方法來取代該實現以提高其性能。C++中的字符串生產者/消費者:std :: deque <char>或std :: stringstream?

我需要的語義是標準類queue的語義:推在前面,在後面彈出。默認實現使用deque IIRC。 deque通常是使用內存的「塊」或「塊」來實現的,所以我期望調用OS內存分配器的次數少得多,而且速度顯着提高,並且只需很少的額外內存使用量。

但是,由於排隊的數據是字符(可能是寬字符),所以可以使用標準輸入/輸出流類,即字符流stringstream。 AFAIK,他們的行爲也像隊列一樣。

先驗是否有更好的選擇?這兩個類是否有類似的分配模式?我可以嘗試和衡量兩者的表現,但也許它並不重要,或者是足夠好的。在那種情況下,哪個最簡單/最安全?

次要問題是生產者和消費者之間的併發。我可以將訪問限制爲順序的(在同一個線程上),但對於當前的多核硬件,線程安全的實現可能在性能方面是有益的。

感謝您的智慧,然後再潛入並開始編碼。

+0

我可能會去'std :: deque',因爲它是專門爲處理這種情況而設計的。另一種可能性是固定大小的隊列,當隊列滿時就會阻塞。通過適當的大小,阻塞通常實際上是可取的(如果一方太落後,阻塞可以給它更多的CPU時間,以便有機會趕上)。 –

+0

std :: deque的連續內存需求可能會影響性能,消費者的一些大型realloc不夠快。雖然嘗試它可能是最好的答案 –

+1

我不認爲'std :: deque'具有連續的內存要求。事實上,Josuttis說的相反。 –

回答

1

std::stringstream不是隊列,因爲閱讀字符不會消耗它們。你可以簡單地seekg(0)並重新閱讀相同的字符。因此,你寫得越多,你消耗的內存就越多。

堅持std::queue。作爲底層實現的默認選擇std::deque幾乎肯定是正確的。

關於併發性,當任何其他線程正在讀取或寫入時,寫入std::queue是絕對不安全的。如果你想要一個有效的阻塞隊列實現,你必須編寫或借用專門爲此目的而構建的一個。

+0

std :: deque沒有要求釋放內存到操作系統,即使它是空的 - 這可能是OP –

+0

@AdrianCornish的考慮:好點。很難想象一個理智的實現不會釋放或重複使用掉落在鏈條末端的塊。但是,這當然不是一個保證。在C++ 11中,我想可以明智地使用['std :: deque :: shrink_to_fit'](http://en.cppreference.com/w/cpp/container/deque/shrink_to_fit)。 –

+0

@MarceloCanton - 酷 - 不知道存在 - 謝謝。雖然我有新的標準 - 從頭到尾閱讀它還沒有發生;-) –

1

很多年前我讀過這本書(我認爲,沒有再讀過),他們實際上是在他們開始在他們破產之前開始要求爲它購買雜誌之前寄給我的雜誌的:-)。

這可能有助於

http://www.drdobbs.com/parallel/lock-free-queues/208801974

作爲一個方面說明我的實時系統的工作處理金融數據 - 我們用固定長度隊列通常扔掉,將不適合在如果隊列數據消費者無法處理它 - 舊數據比錯過的數據更糟糕。當然你的要求可能會有所不同。

+1

就像這樣的一個註釋:如果你打算使用一個固定長度的隊列,你通常會將它實現爲一個循環緩衝區。 –

+0

實際上,我們使用SystemV IPC隊列 - 但是,如果您可以阻止生產者覆蓋消費者當前正在閱讀的數據,則循環更好。 –

+0

我看過那篇文章,還有赫伯薩特的後續。 TL; DR:很難!至少作爲第一步,我會放棄線程... –