2009-04-11 160 views
0

我通過Boost.Serialization反序列化相當數量的數據(每幀一個)。但是,當我輸出反序列化需要多長時間時,其變化很大。目前這個速度並不是不可靠的,但是加快速度會更好。數據表示相同的類,數組,地圖和矢量,但僅具有不同的值。Boost反序列化優化?

考慮到每個反序列化發生時的內存尖峯效應,我不得不相信,這樣做比繼續分配和釋放所有這些內存有更好的方式。

這裏有幾個讀取時間爲例子:

Deserialization - 390 milliseconds 
Deserialization - 422 milliseconds 
Deserialization - 422 milliseconds 
Deserialization - 422 milliseconds 
Deserialization - 438 milliseconds 
Deserialization - 2156 milliseconds 
Deserialization - 1797 milliseconds 
Deserialization - 1656 milliseconds 
Deserialization - 1328 milliseconds 
Deserialization - 1219 milliseconds 
Deserialization - 1078 milliseconds 
Deserialization - 1078 milliseconds 

有編寫自定義的反序列化功能對於使用Boost.Serialization這樣我就可以在指定分配內存相同數據的方法開始,然後只是改變它們的值爲每個幀?

更新:我意識到我使用的優化標誌的一個小問題是導致序列化數據寫入不正確,導致反序列化時間不一致。解決這個問題之後,現在每幀一直在750-780毫秒。當我真的只想序列化內容(因爲容器的大小和索引保持完全相同)時,我的原始問題仍然存在,因爲目前我正在序列化和反序列化整個stl容器。我不確定最好的方式去做這件事。

+0

什麼框架?視頻也許?另外,從運行到運行的各個幀 - 反序列化時間是否可重複?另外,你是從硬盤或內存讀取輸入嗎?如果前者,那麼硬盤尋道時間以及幀是否已經被緩存可能會主宰其他所有。 – 2009-04-11 15:15:57

+0

基本上的視頻幀(儘管它實際上是表示數據)。看到我對這個問題的更新。關於輸入,它都是從磁盤序列化和反序列化的。也許在循環幀之前將數據從磁盤初始傳輸到內存會有所幫助。 – Dan 2009-04-11 16:30:52

回答

3

您可能想重新考慮使用此序列化功能的設計。

從您的描述看來,您似乎很頻繁地序列化/反序列化整個STL容器。這不應該是必需的。不應使用Serialization,除非數據需要保留,以便可以稍後或由其他人重新構建。

如果您的應用程序需要序列化,則可以考慮分別序列化容器中的每個項目,然後僅在項目更改時重新序列化。這樣你就不會不必要地重新做所有的工作。

1

聲明:我不使用boost序列化。

這就是說:這些問題的標準問題或多或少是你所描述的:對於任何單一的序列化,你從操作系統請求幾個(有時是很多)內存塊,然後你釋放它們,當你實際上或多或少地知道你需要多少內存開始。我所知道的唯一解決方案是實現類似於Apache「池」的東西:您分配一塊內存並讓您的分配器(您向stl或boost提供的內存)在此池中工作;那麼你有像Pool :: string這樣的類來分配池內的內存。兩個警告:

  • 是的,這是不是很C++十歲上下,但你可以把它周圍的一個很好的信封(系統架構師,我的工作做了這樣的事情)。
  • 是的,你必須照顧你需要分配另一個池的情況。
0

我的第一個建議,因爲我看不到你的代碼,將使用一個分析工具來確定實際的瓶頸。

內存分配/解除分配可能是核心問題,在這種情況下,池分配 - 假定您有固定大小的對象 - 就像David提到的那樣。可能會有所幫助。

如果將大量對象序列化爲常規的ASCII格式文件,從ASCII到二進制的轉換可能會消耗一些不平凡的時間。 atoi()的等價物可能很快,但是當你說「frame」時,我假設某種圖片或網絡緩衝區,並且它可能很大/很長。所以atoi()的開銷可能會在數百萬次以後顯着增加。

我不明白你在內容和對象之間做出的區別。總的來說,在空間方面收集的開銷並不多,在散列和樹重新平衡方面可能會有一些「時間」,但分析器也應該顯示這一點。

總之,你認爲的部分很慢,可能會對整體性能產生有限的影響。配置文件,並確認。

1

Boost序列化爲STL集合提供了模板化的保存方法,例如,一套:

template<class Archive, class Key, class Compare, class Allocator > 
inline void save(
    Archive & ar, 
    const std::set<Key, Compare, Allocator> &t, 
    const unsigned int /* file_version */ 
){ 
    boost::serialization::stl::save_collection< 
     Archive, std::set<Key, Compare, Allocator> 
    >(ar, t); 
} 

其中只是委託save_collection。我想你可以定義爲專業化它執行序列化在您選擇的方式您的收藏類型,例如:

namespace boost { 
namespace serialization { 

template<class Archive> 
inline void save<MyKey, MyCompare, MyAlloc> (
    Archive & ar, 
    const std::set<MyKey, MyCompare, MyAlloc> &t, 
    const unsigned int /* file_version */ 
){ 
    // ... 
} 

} 
} 

你可以採取save_collection實施的複印件(collections_save_imp.hpp)爲起點,並對其進行優化以符合您的要求。例如。使用一個類來記錄前一次調用的集合大小,如果它沒有改變,則重新使用相同的緩衝區。

您可能還需要專門針對您的成員類型。在哪一點上,如果你從boost序列化中獲得任何價值,這是值得懷疑的。

我知道這是一個有點模糊,但它很難更具體不知道你使用的集合類型,成員類型是什麼等