2016-12-21 3 views
4

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

Я хочу быстро создать индекс имен наборов данных. Пример файла - около 21 МБ и содержит 88 наборов данных. Чтение 88 имен быстро с помощью std::ifstream и seekg() для пропуска между наборами данных занимает около 1300 мс, что я хотел бы уменьшить.

На самом деле, я читаю 88 кусков около 30 байт, на данных позициях в файле 21 МБ, и это занимает 1300 мс.

Есть ли способ улучшить это, или это ограничение ОС и файловой системы? Я запускаю тест под Windows 7 64bit.

Я знаю, что иметь полный индекс в начале файла будет лучше, но формат файла не имеет этого, и мы не можем его изменить.

+0

Некоторые подсказки на http://stackoverflow.com/questions/5166263/how-to-get-iostream-to-perform-better –

+0

Являются ли эти текстовые файлы? Сохраняет ли Windows как возврат каретки, так и линию в конце строк? Если это так, ищет ли поиск по логическому текстовому файлу с ifstream, отфильтровывая символы возврата каретки? Если это так, возможно, вы можете открыть файл в необработанном двоичном режиме и, таким образом, запретить функции поиска читать все символы, чтобы избежать включения CR в смещение поиска? Но тогда, конечно, ваш код, возможно, придется игнорировать нефильтрованные возвращения каретки. – WaltK

+0

Разделение в 88 небольших файлов с неизменным форматом данных - опция для вас? – norca

ответ

2

Вы можете сканировать файл и создать собственный заголовок с ключом и индексом в отдельном файле. В зависимости от вашего варианта использования вы можете сделать это один раз при запуске программы и каждый раз, когда файл изменяется. Перед доступом к большим данным поиск в файле меньшего размера дает вам необходимый индекс.

5

Вы можете использовать память отображается интерфейс файла (я рекомендую boost's implementation.)

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

+0

Я не вижу, как это могло бы избежать необходимости искать головки дисков назад и вперед; главным отличием будет то, что ОС отправляет команды поиска вместо приложения. –

+0

@JeremyFriesner Ни в коем случае не избегает начального поиска головки диска. Основное различие заключается в том, что страницы живут в ядре памяти, доступ к которой вы можете получить напрямую, а не в пространстве пользователя, которое выполняется iostreams. – mascoj

+0

это не (относительно незначительная) копия из ядра в пользовательское пространство, которую ОП пытается свести к минимуму, это поиск головок дисков. Использование mmap() не позволяет избежать этих запросов, и на самом деле может добавить больше (в зависимости от того, как реализация OS-алгоритма lookahead взаимодействует с шаблонами, в которых программа OP обращается к области памяти mmap()). –

0

Возможно, вы выполните процедуру буферизации с многопоточным процессом. Вы можете создать настраиваемую структуру, которая будет хранить различные объемы данных.

Вы сказали:

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

Так как открытие и закрытие файлов снова и снова происходит медленно, вы можете прочитать файл за один раз и сохранить его в полный буферный объект, а затем проанализировать или сохранить его в партии. Это также будет зависеть от того, читаете ли вы в текстовом или двоичном режиме, насколько легко разбирать файл. Я продемонстрирую позже с заполнением нескольких партий при чтении в буферном размере количества данных из файла.

псевдокоде

struct Batch { 
    std::string name; // Name of Dataset 
    unsigned size; // Size of Dataset 
    unsigned indexOffset; // Index to next read location 
    bool empty = true;  // Flag to tell if this batch is full or empty 
    std::vector<DataType> dataset; // Container of Data 
}; 

std::vector<Batch> finishedBatches; 

// This doesn't matter on the size of the data set; this is just a buffer size on how much memory to digest in reading the file 
const unsigned bufferSize = "Set to Your Preference" 1MB - 4MB etc. 

void loadDataFromFile(const std::string& filename, unsigned bufferSize, std::vector<Batch>& batches) { 

    // Set ifstream's buffer size 

    // OpenFile For Reading and read in and upto buffer size 

    // Spawn different thread to populate the Batches and while that batch is loading 
    // in data read in that much buffer data again. You will need to have a couple local 
    // stack batches to work with. So if a batch is complete and you reached the next index 
    // location from the file you can fill another batch. 

    // When a single batch is complete push it into the vector to store that batch. 
    // Change its flag and clear its vector and you can then use that empty batch again. 

    // Continue this until you reached end of file.   

} 

Это будет система 2 Резьбовое здесь. Основной поток для открытия и чтения из файла и поиска из файла с рабочим потоком, заполняющим партии, и выталкиванием партий в контейнер и заменой для использования следующей партии.

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