Уменьшить объем сериализации
От: k732  
Дата: 20.06.08 03:31
Оценка:
Есть объект, отвечающий за усреднение значений

template <typename T, uint N = 32>
class Averager {
private :
    friend class boost::serialization::access;

    std::deque<T> m_deque;
    uint64 m_sum;
    uint m_size;

    template <class Archive>
    void serialize (Archive& archive, const uint version)
    {
        archive & BOOST_SERIALIZATION_NVP (m_deque);
        archive & BOOST_SERIALIZATION_NVP (m_sum);
        archive & BOOST_SERIALIZATION_NVP (m_size);
    }

public :
    explicit Averager(uint size = N) : m_sum (0), m_size (size) {}
    ~Averager() {}

    Averager& operator += (const Averager& rhs)
    {
        (*this) << rhs.avg();
        return *this;
    }
    void avg (uint size)
    {
        m_sum = 0;
        m_deque.clear();
        m_size = size;
    }
    T avg (void) const
    {
        if (!m_deque.size()) return 0;
        return (T)(m_sum / m_deque.size());
    }
    Averager& operator << (const T& value)
    {
        if (m_size)
        {
            if (m_deque.size() == m_size)
            {
                m_sum -= (*(m_deque.begin()));
                m_deque.pop_front();
            }
            m_sum += value;
            m_deque.push_back(value);
        }
        return *this;
    }   
};


есть объект его использующий

class Item {
private :
    friend class boost::serialization::access;
    typedef Averager<uint> TAverager;
    static const uint AVERAGE = 1000;

    time_t m_time;
    TAverager m_values;

    template <class Archive>
    void serialize (Archive& archive, const uint version)
    {
        archive & BOOST_SERIALIZATION_NVP (m_time);
        archive & BOOST_SERIALIZATION_NVP (m_values);
    }

public :
    Item () : m_time (0), m_values(AVERAGE) {}
    ~Item() {}

    time_t  time (void) const { return m_time;          }
    uint    value(void) const { return m_values.avg();  }

    bool operator < (const Item& rhs) const { return m_time < rhs.m_time; }
    Item& operator << (uint value)
    {
        m_time  =  ::time();
        m_values << value;
        return *this;
    }
};


Так вот если усреднять по очень большому числу значений, то сериализуется весь std::deque.
В результате получаются килобайты, ходя реально интерисует время и усредненное значение (тоесть несколько байт).

Сам дек целиком нужен лишь с одной стороны. Если его передать, сереализовав данные, то на другой нужно лишь усредненное.
Можно ли как сделать, чтоб при сериализации бралось лишь усредненное значение, а при десериализации оно и использовалось для инициализации дека ?

P.S. И хотелось бы это сделать не как в Averager, так и в Item (тоесть двумя способами на выбор)
Re: Уменьшить объем сериализации
От: Vinick Россия  
Дата: 20.06.08 04:37
Оценка:
Здравствуйте, k732, Вы писали:
K>Сам дек целиком нужен лишь с одной стороны. Если его передать, сереализовав данные, то на другой нужно лишь усредненное.
K>Можно ли как сделать, чтоб при сериализации бралось лишь усредненное значение, а при десериализации оно и использовалось для инициализации дека ?

А если разделить чтение и запись как здесь
Splitting serialize into save/load
Re[2]: Уменьшить объем сериализации
От: agolubtsov Россия  
Дата: 20.06.08 05:11
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Здравствуйте, k732, Вы писали:

K>>Сам дек целиком нужен лишь с одной стороны. Если его передать, сереализовав данные, то на другой нужно лишь усредненное.
K>>Можно ли как сделать, чтоб при сериализации бралось лишь усредненное значение, а при десериализации оно и использовалось для инициализации дека ?

V>А если разделить чтение и запись как здесь

V>Splitting serialize into save/load

И не забываем про второй параметр метода serialize
пускай если version = 1, то сериализуем среднее иначе весь объект
Re[3]: Уменьшить объем сериализации
От: k732  
Дата: 20.06.08 07:05
Оценка:
Здравствуйте, agolubtsov, Вы писали:

A>Здравствуйте, Vinick, Вы писали:


V>>Здравствуйте, k732, Вы писали:

K>>>Сам дек целиком нужен лишь с одной стороны. Если его передать, сереализовав данные, то на другой нужно лишь усредненное.
K>>>Можно ли как сделать, чтоб при сериализации бралось лишь усредненное значение, а при десериализации оно и использовалось для инициализации дека ?

V>>А если разделить чтение и запись как здесь

V>>Splitting serialize into save/load

A>И не забываем про второй параметр метода serialize

A>пускай если version = 1, то сериализуем среднее иначе весь объект

ну впринципе идея понятна. Только
1. Как сериализатору указать версию (желательно, чтоб полностью сериализовалось по умолчанию)
2. Я так понимаю, что нужно что-то вроде

    template<class Archive>
    void save (Archive& archive, const unsigned int version) const
    {
        archive & m_time;
        archive & (!version) ? m_values : m_values.avg();
    }
    template<class Archive>
    void load (Archive& archive, const unsigned int version)
    {
        archive & m_time;
        archive & (!version) ? m_values : ... ?;
    }


тоесть для сериализации понятно: если version = 0, то сериализуем весь объект, иначе только среднее значение (int)
А вот при десереализации если 0, то опять весь контейнер, а вот если не 0, то нужно как-то проинициализировать объект руками.

Вот здесь я просто не понял как
Re[4]: Уменьшить объем сериализации
От: Vinick Россия  
Дата: 20.06.08 07:38
Оценка:
Здравствуйте, k732, Вы писали:

K>тоесть для сериализации понятно: если version = 0, то сериализуем весь объект, иначе только среднее значение (int)

K>А вот при десереализации если 0, то опять весь контейнер, а вот если не 0, то нужно как-то проинициализировать объект руками.

K>Вот здесь я просто не понял как

Не совсем понятно зачем инициализировать то что получателю не требуется. Может проще ввести в Averager поле m_avg и какой-нибудь флаг сигнализирующий о валидности этого поля.
Но если очень хочется иметь заполненый контейнер, то так:
    template<class Archive>
    void save (Archive& archive, const unsigned int version) const
    {
        archive & version;
                archive & m_time;
                if(!version)
                   archive & m_values;
                else
                  {
                     archive & m_values.deque_size();
                     archive & m_values.avg();
                  }
    }
    template<class Archive>
    void load (Archive& archive, const unsigned int)
    {
                int version;
                archive & version;
        archive & m_time;
                if(!version)
                     archive & m_values;
                else
                   {
                       uint sz;
                       double avg;
                       archive & sz;
                       archive & avg;
                       m_values.avg(sz);
                       std::fill_(std::ostream_iterator<double>(m_values),sz,avg);
                       // или если сохранение размера не важно m_values << avg,
                       // тогда передавать m_values.deque_size() нет необходимости
                    }
    }
Re[5]: Уменьшить объем сериализации
От: k732  
Дата: 20.06.08 07:46
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Здравствуйте, k732, Вы писали:


K>>тоесть для сериализации понятно: если version = 0, то сериализуем весь объект, иначе только среднее значение (int)

K>>А вот при десереализации если 0, то опять весь контейнер, а вот если не 0, то нужно как-то проинициализировать объект руками.

K>>Вот здесь я просто не понял как

V>Не совсем понятно зачем инициализировать то что получателю не требуется. Может проще ввести в Averager поле m_avg и какой-нибудь флаг сигнализирующий о валидности этого поля.
V>Но если очень хочется иметь заполненый контейнер, то так:
V>
V>    template<class Archive>
V>    void save (Archive& archive, const unsigned int version) const
V>    {
V>        archive & version;
V>                archive & m_time;
V>                if(!version)
V>                   archive & m_values;
V>                else
V>                  {
V>                     archive & m_values.deque_size();
V>                     archive & m_values.avg();
V>                  }
V>    }
V>    template<class Archive>
V>    void load (Archive& archive, const unsigned int)
V>    {
V>                int version;
V>                archive & version;
V>        archive & m_time;
V>                if(!version)
V>                     archive & m_values;
V>                else
V>                   {
V>                       uint sz;
V>                       double avg;
V>                       archive & sz;
V>                       archive & avg;
V>                       m_values.avg(sz);
V>                       std::fill_(std::ostream_iterator<double>(m_values),sz,avg);
V>                       // или если сохранение размера не важно m_values << avg,
V>                       // тогда передавать m_values.deque_size() нет необходимости
V>                    }
V>    }
V>


спасибо. я правда уже немного по-другому сделал

    template<class Archive>
    void save (Archive& archive, const unsigned int version) const
    {
        archive << m_time;
        if (version)
        {
            TAverager temp (1);
            temp << m_values.avg();
            archive << temp;
        }
        else archive << m_power;
    }
    template<class Archive>
    void load (Archive& archive, const unsigned int version)
    {
        archive >> m_time;
        if (version)
        {
            TAverager temp (1);
            archive >> temp;
            m_values << temp.avg();
        }
        else archive >> m_power;
    }


я так понимаю, что осталось выбрать версию
BOOST_SERIALIZATION_SPLIT_MEMBER()
...
BOOST_CLASS_VERSION (Item, 1)

но получается, что это на этапе компиляции. Тоесть при сериализации всегда пойдет только усредненное значение.
А можно ли на этапе выполнения выбирать ?
Re[5]: Уменьшить объем сериализации
От: k732  
Дата: 20.06.08 07:50
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Здравствуйте, k732, Вы писали:


K>>тоесть для сериализации понятно: если version = 0, то сериализуем весь объект, иначе только среднее значение (int)

K>>А вот при десереализации если 0, то опять весь контейнер, а вот если не 0, то нужно как-то проинициализировать объект руками.

K>>Вот здесь я просто не понял как

V>Не совсем понятно зачем инициализировать то что получателю не требуется. Может проще ввести в Averager поле m_avg и какой-нибудь флаг сигнализирующий о валидности этого поля.
V>Но если очень хочется иметь заполненый контейнер, то так:
V>
V>    template<class Archive>
V>    void save (Archive& archive, const unsigned int version) const
V>    {
V>        archive & version;
V>                archive & m_time;
V>                if(!version)
V>                   archive & m_values;
V>                else
V>                  {
V>                     archive & m_values.deque_size();
V>                     archive & m_values.avg();
V>                  }
V>    }
V>    template<class Archive>
V>    void load (Archive& archive, const unsigned int)
V>    {
V>                int version;
V>                archive & version;
V>        archive & m_time;
V>                if(!version)
V>                     archive & m_values;
V>                else
V>                   {
V>                       uint sz;
V>                       double avg;
V>                       archive & sz;
V>                       archive & avg;
V>                       m_values.avg(sz);
V>                       std::fill_(std::ostream_iterator<double>(m_values),sz,avg);
V>                       // или если сохранение размера не важно m_values << avg,
V>                       // тогда передавать m_values.deque_size() нет необходимости
V>                    }
V>    }
V>


и зачем сериализовать саму версию ?
Re[6]: Уменьшить объем сериализации
От: Vinick Россия  
Дата: 20.06.08 13:57
Оценка:
Здравствуйте, k732, Вы писали:

K>и зачем сериализовать саму версию ?

А как получатель узнает о том какой объект лежит в архиве?
Re[7]: Уменьшить объем сериализации
От: k732  
Дата: 20.06.08 20:02
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Здравствуйте, k732, Вы писали:


K>>и зачем сериализовать саму версию ?

V>А как получатель узнает о том какой объект лежит в архиве?
Понятно. Принимается...

Есть еще вопросы
1. Почему я не могу сериализовать данные контейнера.


V>                else
V>                  {
V>                     archive & m_values.size();  // size добавил
V>                     archive & m_values.avg();
V>                  }



>*.h(152) : error C2664: 'boost::serialization::make_nvp' : cannot convert parameter 2 from 'unsigned int' to 'unsigned int &'
1>        C:\BOOST\boost_1_35_0\boost/serialization/access.hpp(93) : see reference to function template instantiation 'void Averager<T>::save<Archive>(Archive &,const unsigned int) const' being compiled
1>        with
1>        [
1>            T=uint,
1>            Archive=boost::archive::binary_oarchive
1>        ]
1>        C:\BOOST\boost_1_35_0\boost/serialization/split_member.hpp(43) : see reference to function template instantiation 'void boost::serialization::access::member_save<Archive,const T>(Archive &,T &,const unsigned int)' being compiled
1>        with
1>        [
1>            Archive=boost::archive::binary_oarchive,
1>            T=Averager<uint>
1>        ]
...


а получается только так

            value_type avg = this->avg();
            uint size = m_m_values.size();
            archive & BOOST_SERIALIZATION_NVP (size);
            archive & BOOST_SERIALIZATION_NVP (avg);


В чем разница ?

2.Хчется сериализовать Averager

Сериализация зависит от версии. Ее нужно задать как
BOOST_CLASS_VERSION (SomeClass, version)

Для нешаблонных классов получается задавать версию, но Averager шаблонный и не понятно как для него вызвать
BOOST_CLASS_VERSION. Тоесть нужно как-то указать для всех типов.

Можно или нет ?
Re: Уменьшить объем сериализации
От: NikeByNike Россия  
Дата: 20.06.08 22:25
Оценка:
Здравствуйте, k732, Вы писали:

[крик души]
Сволочная бустовская сериализация.
[/крик души]
Нужно разобрать угил.
Re[2]: Уменьшить объем сериализации
От: k732  
Дата: 21.06.08 07:29
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, k732, Вы писали:


NBN>[крик души]

NBN>Сволочная бустовская сериализация.
NBN>[/крик души]

ну это не решпет вышеописанные проблеммы
Re[2]: Уменьшить объем сериализации
От: k732  
Дата: 21.06.08 12:32
Оценка: :)
ну где Вы, корифеи ? (сейчас правда принято Guru

Странно конечно, что такой мощнейший форум (вывод сделал по некоторым индивидумам)
и так не активен в последнее время. Он доживает ?

Если да, то где сейчас все тусуются, если нет, то где кипящая жизнь, обмен опытом...

Или все к футболу готовятся ?
Re[3]: Уменьшить объем сериализации
От: NikeByNike Россия  
Дата: 21.06.08 12:56
Оценка:
Здравствуйте, agolubtsov, Вы писали:

A>И не забываем про второй параметр метода serialize

A>пускай если version = 1, то сериализуем среднее иначе весь объект

Проблема в том, что версия записывается только один раз на тип. И в этом заключается большая подстава.
Нужно разобрать угил.
Re[4]: Уменьшить объем сериализации
От: k732  
Дата: 21.06.08 13:00
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, agolubtsov, Вы писали:


A>>И не забываем про второй параметр метода serialize

A>>пускай если version = 1, то сериализуем среднее иначе весь объект

NBN>Проблема в том, что версия записывается только один раз на тип. И в этом заключается большая подстава.

Ну пусть хоьб 1 раз. Но проблемма в шаблонном классе. Можно ли ее разрешить ?
Re: Уменьшить объем сериализации
От: NikeByNike Россия  
Дата: 21.06.08 13:00
Оценка:
Здравствуйте, k732, Вы писали:

А если ввести флажок — обозначающий содержимое твоего Averager и при необходимости итема:
    std::deque<T> m_deque;
    uint64 m_sum;
    uint m_size;
    bool m_use_only_mean;

    template <class Archive>
    void serialize (Archive& archive, const uint version)
    {
        archive & BOOST_SERIALIZATION_NVP (m_use_only_mean);
        if ( !m_use_only_mean )
            archive & BOOST_SERIALIZATION_NVP (m_deque);
        archive & BOOST_SERIALIZATION_NVP (m_sum);
        archive & BOOST_SERIALIZATION_NVP (m_size);
    }

Такое тебе не годится?
Нужно разобрать угил.
Re[2]: Уменьшить объем сериализации
От: k732  
Дата: 21.06.08 13:03
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, k732, Вы писали:


NBN>А если ввести флажок — обозначающий содержимое твоего Averager и при необходимости итема:

NBN>
NBN>    std::deque<T> m_deque;
NBN>    uint64 m_sum;
NBN>    uint m_size;
NBN>    bool m_use_only_mean;

NBN>    template <class Archive>
NBN>    void serialize (Archive& archive, const uint version)
NBN>    {
NBN>        archive & BOOST_SERIALIZATION_NVP (m_use_only_mean);
NBN>        if ( !m_use_only_mean )
NBN>            archive & BOOST_SERIALIZATION_NVP (m_deque);
NBN>        archive & BOOST_SERIALIZATION_NVP (m_sum);
NBN>        archive & BOOST_SERIALIZATION_NVP (m_size);
NBN>    }


NBN>

NBN>Такое тебе не годится?
как вариант конечно можно
ну раз пошла пьянка с бустом, что хотелось бы разобраться...
Re[3]: Уменьшить объем сериализации
От: Erop Россия  
Дата: 21.06.08 13:48
Оценка:
Здравствуйте, k732, Вы писали:

K>Если да, то где сейчас все тусуются, если нет, то где кипящая жизнь, обмен опытом...

Да просто все тебя жалеют и не дают советы, типа, выпрями таки дизайн и сделать так, чтобы сериализация была отдельно, а модификация данных отдельно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Уменьшить объем сериализации
От: Sergey Россия  
Дата: 21.06.08 15:18
Оценка:
k732 пишет:

> Ну пусть хоьб 1 раз. Но проблемма в шаблонном классе. Можно ли ее

> разрешить ?


Попробуй ченить в таком роде:
namespace boost { namespace serialization {
template<typename T, unsigned int X> struct version<Averager<T, X> >
{
    typedef mpl::int_<20> type;
    typedef mpl::integral_c_tag tag;
    BOOST_STATIC_CONSTANT(unsigned int, value=version::type::value);
};
}}


Не знаю, на кой ляд там mpl-ные штуки, наверное можно написать просто
namespace boost { namespace serialization {
template<typename T, unsigned int X> struct version<Averager<T, X> >
{
     enum { value = 20};
};
}}
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[6]: Уменьшить объем сериализации
От: NikeByNike Россия  
Дата: 21.06.08 15:31
Оценка:
Здравствуйте, Sergey, Вы писали:

S>Попробуй ченить в таком роде:

S>Не знаю, на кой ляд там mpl-ные штуки, наверное можно написать просто

Версия сохраняется только один раз, поэтому в общем случае её лучше применять для именно версионных целей.
Нужно разобрать угил.
Re[7]: Уменьшить объем сериализации
От: Sergey Россия  
Дата: 21.06.08 15:49
Оценка:
NikeByNike пишет:

> S>Попробуй ченить в таком роде:

> S>Не знаю, на кой ляд там mpl-ные штуки, наверное можно написать просто
>
> Версия сохраняется только один раз, поэтому в общем случае её лучше
> применять для именно версионных целей.

Я честно говоря не разбирался, для чего там k732 версию применять
пытается. Понял, что она нужна для шаблонного класса, заглянул в
исходники и написал как ее на мой взгляд можноь применить не к классу, а
к шаблону — эта задача, по-моему, может не только у него возникнуть.
А уж будет в нее k732 собственно версию класть или какие-то левые
извраты, меня не касается.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.