2015-08-11 2 views
1

У меня есть требование взять структуру и выгрузить ее в файл для последующего использования. Это должно быть как можно быстрее.Бинарный журнал с привязкой к памяти в C++

Проведя эксперименты с различными решениями, я пришел к выводу, что memcpy() для файла с отображением памяти (с огромными страницами) является самым быстрым решением проблемы. Есть ли лучший подход?

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

+1

Под «более поздним использованием» вы имеете в виду позже в том же исполнении или позже, когда программа будет выполнена снова? В последнем случае вам нужно будет использовать 'msync', чтобы изменения отображались в файле (если вы используете linux или другое posix). – skyking

+0

Являются ли структуры POD или нетривиальными классами? –

+0

@skyking: Я имел в виду, что буду использовать данные в отдельной программе для анализа. Эта часть не чувствительна к производительности. – noobie

ответ

2

Вот пример использования Boost.Interprocess:

#include <boost/interprocess/file_mapping.hpp> 
#include <boost/interprocess/mapped_region.hpp> 
#include <fstream> 
#include <string> 

namespace ip = boost::interprocess; 

struct example { 
    int data; 
    // etc. 
}; 

const char * filename = "/path/to/file"; 
int main() { 
    // Remove existing mapping 
    ip::file_mapping::remove (filename); 

    // Create file 
    std::filebuf fb; 
    fb.open(filename, std::ios_base::in | std::ios_base::out 
          | std::ios_base::trunc | std::ios_base::binary); 
    fb.pubseekoff (sizeof (example)-1, std::ios_base::beg); 
    fb.sputc (0); 

    // Map to file 
    ip::file_mapping mapping (filename, ip::read_write); 

    // map a region 
    ip::mapped_region region (mapping, ip::read_write); 

    // Get mapped address 
    void *addr = region.get_address(); 

    // copy struct to file 
    example ex; 
    memcpy (addr, &ex, sizeof (example)); 

    // flush to disk 
    region.flush(); 
} 

Чтобы получить данные из сопоставьте в файл таким же образом (хотя, возможно только с READ_ONLY доступа). То, что может вас убить, - это флеш на диск, который может занять некоторое время.

В идеале вы должны попробовать сопоставленную версию файла и простую версию iostream от Tanzer's Answer. Измерьте производительность как на целевой платформе, так и выберите лучший.

+0

Спасибо за фрагмент кода. Я делаю почти то же самое со стандартным C++ API. И если я правильно измеряю, это самое быстрое, что может пойти (доля микросекунды для 512-байтового сообщения на измеренной машине). Я не делаю флеш(), хотя, позволяя ОС позаботиться об этом. Действительно ли промывка вручную необходима? Я не против, если данные теряются из-за случайных сбоев. – noobie

+0

Промывка не является обязательной. Кроме того, в зависимости от вашей платформы это, вероятно, будет выполняться асинхронно; вызов 'flush()' просто заставляет его закрашиваться в фоновом режиме. – Anthony

1

Вы можете использовать классы ifstream и ofstream для записи ваших объектов в виде двоичных файлов.

struct anyobj; 

ofstream ofs("file.bin",ios::binary); 
ofs.write ((char*) & anyobj , sizeof(anyobj)); 

Тогда читайте

struct anyobj2; 

ifstream ifs ("file.bin", ios::binary); 
ifs.read((char*) & anyobj2 , sizeof(anyobj2)); 

Но вы должны заботиться о подобных ситуациях в различных системах (портативность) и компиляторов (различные стратегии прокладки).

Смежные вопросы