шарить сложные структуры м\у программами

NataNata

есть N instance-ов одной программы, каждый из которых подгружает с винта одни и те же данные, с которыми в дальнейшем проводит некоторые свои вычисления. Объемы данных - десятки гигабайт. Программа написаны на c++ из-за требований по скорости работы. Данные достаточно сложны и ветвисты, посему в памяти завожу структуры, состоящие из массы STL контейнеров. В последнее время памяти стало не хватать (уже требуются сотни гигов поэтому хочется, чтобы 1 instance пргограммы загружал бы данные, а другие доступались бы до них напрямую через механизмы shared memory.
Не мог бы кто-нибудь подсказать стандартный способ для расшаривания посредством shared memory сложных c++-ных структур, в которых полно STL контейнеров?
Я понимаю, что для используемых с++-ных структур можно собрать аналоги с-ных структур, в которых идет адресация через поинтеры, а данные хранить в одном непрерывном многогигабайтном куске (который и share-ить но вручную такой фокус мне весьма неохота проворачивать, ибо неизящно.
Купить машину, где дофига памяти - не вариант по административным причинам..
Перевести приложение в многопоточное - не вариант по техническим причинам.

agaaaa

На всякий случай уточню. Структуры у тебя - только для чтения?

domovoj

Boost.Interprocess

kill-still

у хазелкаста платного вроде есть клиент на С++ http://hazelcast.com/products/hazelcast-enterprise/
но он сам на яве.

NataNata

Да, только для чтения

zya369

сначала считать, потом форкнуться?

istran

Попробуй http://github.com/yandex/mms. Эту либу написали и используют в Я.Картах. Собственно, можно создавать произвольные структуры данных с поддержкой стандартных контейнеров (точнее контейнеров с таким же интерфейсом, как у стандартных). Загрузка в память сериализованной структуры осуществляется одним mmap-ом файла, засчет чего можно шарить ее между несколькими процессами. Вот пример использования:

template<class P>
struct My {
int i;
mms::string<P> str;
mms::map<P, mms::string<P>, int> map;

// Expose struct's fields to mms
template<class A> void traverseFields(A a) const { a(istrmap); }
};

int main
{
// Populate the struct
My<mms::Standalone> my;
my.i = 22;
my.str = "a string";
my.map.insert(std::make_pair("ten", 10;
my.map.insert(std::make_pair("eleven", 11;
my.map.insert(std::make_pair("twelve", 12;

// Serialize it
std::ofstream out("filename");
size_t pos = mms::write(out, my);
out.close;

// mmap serialized data
int fd = ::open("filename", O_RDONLY);
struct stat st;
fstat(fd, &st);
char* data = (char*) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
const My<mms::Mmapped>* pmy = reinterpret_cast<const My<mms::Mmapped>*>(data + pos);

// Use the data
std::cout << pmy->i << std::endl;
std::cout << pmy->str << std::endl;
std::cout << pmy->map.size << std::endl;
std::cout << pmy->map["twelve"] << std::endl;
}

Вот тут http://tech.yandex.ru/events/cpp-party/may-nsk/talks/1934/ можно глянуть презентацию, о там как все это устроено.

istran

Я не очень понял правда, почему они не заопенсорсили обертки для (де)сериализации. Я тут нагавнокодил на скорую руку, кажется так менее устрашающе выглядит:

template<class P>
struct My {
int i;
mms::string<P> str;
mms::map<P, mms::string<P>, int> map;

// Expose struct's fields to mms
template<class A> void traverseFields(A a) const { a(istrmap); }
};

template <typename MmsStruct>
void serialize(const MmsStruct& data, const std::string& filename) {
std::ofstream out(filename);
uint64_t pos = mms::write(out, data);
out.write(reinterpret_cast<const char*>(&pos sizeof(pos;
out.close;
}

template <typename MmsStruct>
const MmsStruct* deserialize(const std::string& filename) {
int fd = ::open(filename.c_str O_RDONLY);
lseek(fd, -sizeof(uint64_t SEEK_END);
uint64_t pos = 0;
read(fd, &pos, sizeof(pos;
lseek(fd, 0, SEEK_SET);
struct stat st;
fstat(fd, &st);
char* data = (char*) mmap(0, st.st_size - sizeof(uint64_t PROT_READ,
MAP_SHARED, fd, 0);
close(fd);
return reinterpret_cast<const MmsStruct*>(data + pos);
}

int main
{
// Populate the struct
My<mms::Standalone> my;
my.i = 22;
my.str = "a string";
my.map.insert(std::make_pair("ten", 10;
my.map.insert(std::make_pair("eleven", 11;
my.map.insert(std::make_pair("twelve", 12;

serialize(my, "filename");
const My<mms::Mmapped>* pmy = deserialize<My<mms::Mmapped>>("filename");

// Use the data
std::cout << pmy->i << std::endl;
std::cout << pmy->str << std::endl;
std::cout << pmy->map.size << std::endl;
std::cout << pmy->map["twelve"] << std::endl;
}
Оставить комментарий
Имя или ник:
Комментарий: