Boost logo

Boost :

Subject: [boost] [serialization] de-serialization performance issue
From: Brad Higgins (bhiggins_at_[hidden])
Date: 2011-01-19 15:16:33


I have encountered a performance issue with serialization, when used with multi-index followed by a vector<size_t>. I have a reduced program below, which reproduces the issue (using boost 1.44.0).

I basically have a class with a multi-index member, and a vector<size_t> member. It serializes OK, but deserialization's performance appears to be O(n^2). It seems to be getting bogged down in basic_iarchive_impl::reset_object_address(), when deserializing the vector. Any thoughts?

Thanks,
Brad

-------------------------------------------
#include <iostream>
#include <fstream>
#include <sstream>

#include <string>
#include <vector>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/version.hpp>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

struct DummyItem {
    std::size_t ordered_val_;

    DummyItem(
              const std::size_t ordered_val) :
        ordered_val_(ordered_val)
    {}

    DummyItem() :
        ordered_val_(0)
    {}

    /**
     * Boost serialization hook
     */
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
            ar & boost::serialization::make_nvp("ordered_val",
                    ordered_val_);
    }

};

BOOST_CLASS_VERSION(DummyItem,1)

namespace bmi = boost::multi_index;

class MultiIndexDummy
{
    public:
        struct ordered_val_tag {};
        typedef bmi::multi_index_container<
            DummyItem,
            bmi::indexed_by<
            bmi::ordered_non_unique<
                bmi::tag<ordered_val_tag>,
            BOOST_MULTI_INDEX_MEMBER(DummyItem,std::size_t,ordered_val_)
>
>
> MultiIndexDb;
        typedef MultiIndexDb::index<ordered_val_tag>::type OrderedVal2Index;

        bool insert(DummyItem &item) {
            bool rc = false;
            OrderedVal2Index &str_idx = db_.get<ordered_val_tag>();
            OrderedVal2Index::iterator str_iter = str_idx.find(item.ordered_val_);
            if (str_idx.end() == str_iter) {
                std::pair<OrderedVal2Index::iterator,bool> insert_res
                    = str_idx.insert(item);
                if (insert_res.second) {
                    rc = true;
                }
            }
            return rc;
        }

        MultiIndexDb db_;
        std::vector<std::size_t> vector_ints_;

        /**
         * Boost serialization hook
         */
        friend class boost::serialization::access;
        template<class Archive>
            void serialize(Archive & ar, const unsigned int version)
            {
                std::cout << "SERIALIZE db_\n";
                ar & boost::serialization::make_nvp("db", db_);
                std::cout << "SERIALIZE vector_ints_\n";
                ar & boost::serialization::make_nvp("vector_ints", vector_ints_); // <- THIS IS SLOW DURING INPUT
            }
};

BOOST_CLASS_VERSION(MultiIndexDummy, 1);

int
main(int argc, char* argv[])
{
    const std::string filename("persisted_data.dat");
    std::cout << "Start\n";
    {
        MultiIndexDummy mi_map;
        for (int i=0; i<100000; i++) {
            DummyItem item(i);
            mi_map.insert(item);
            mi_map.vector_ints_.push_back(i);
        }
        std::cout << "persist the data\n";
        std::ofstream out_file(filename.c_str());
        boost::archive::text_oarchive oa(out_file);
        oa.register_type(static_cast<MultiIndexDummy*>(NULL));
        oa << boost::serialization::make_nvp("id", mi_map);
    }
    std::cout << "Restore\n";
    {
        MultiIndexDummy mi_map;
        std::ifstream in_file(filename.c_str());
        boost::archive::text_iarchive ia(in_file);
        ia >> mi_map; // <- THIS IS SLOW
    }

    std::cout << "Done\n";
    return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk