Как прочитать 4ГБ файл в 32-битной системе

В моем случае у меня есть разные файлы, давайте предположим, что у меня есть> 4 ГБ файл с данными. Я хочу читать этот файл построчно и обрабатывать каждую строку. Одно из моих ограничений заключается в том, что софт должен работать на 32-битной MS Windows или на 64-битной с небольшим объемом оперативной памяти (минимум 4 ГБ). Вы также можете предположить, что обработка этих строк не является узким местом.

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

std::ifstream file(filename_xml.c_str());
uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
m_numLines++;
}

И хорошо, это работает, но медленно сейчас время для моих 3,6 ГБ данных:

real    1m4.155s
user    0m0.000s
sys     0m0.030s

Я ищу метод, который будет намного быстрее, чем, например, я обнаружил, что Как быстро проанализировать разделенные пробелами числа в C ++? и мне очень понравилось представленное решение с boost :: mapped_file, но я столкнулся с другой проблемой: что если мой файл слишком большой, а в моем случае файла 1 ГБ достаточно, чтобы отбросить весь процесс. Я должен заботиться о текущих данных в памяти, вероятно, люди, которые будут использовать этот инструмент, имеют не более 4 ГБ установленной оперативной памяти.

Так что я нашел этот mapped_file из boost, но как использовать его в моем случае? Можно ли частично прочитать этот файл и получить эти строки?

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

Спасибо,
Барт

3

Решение

Приятно видеть, что вы нашли мой тест в Как быстро проанализировать разделенные пробелами числа в C ++?

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

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

static uintmax_t wc(char const *fname)
{
static const auto BUFFER_SIZE = 16*1024;
int fd = open(fname, O_RDONLY);
if(fd == -1)
handle_error("open");

/* Advise the kernel of our access pattern.  */
posix_fadvise(fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

char buf[BUFFER_SIZE + 1];
uintmax_t lines = 0;

while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))
{
if(bytes_read == (size_t)-1)
handle_error("read failed");
if (!bytes_read)
break;

for(char *p = buf; (p = (char*) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
++lines;
}

return lines;
}
6

Другие решения

В случае 64-битной системы с небольшой памятью вполне подойдет загрузка большого файла — все дело в адресном пространстве — хотя в этом случае она может быть медленнее, чем «самая быстрая» опция, она действительно зависит от того, что еще в памяти и сколько памяти доступно для отображения файла в. В 32-разрядной системе это не будет работать, поскольку указатели на отображение файлов не будут превышать максимально 3,5 ГБ — и обычно около 2 ГБ — максимум — опять же, в зависимости от того, какие адреса памяти доступны для ОС для сопоставления файла.

Тем не менее, преимущество отображения памяти в файл довольно мало — большая часть времени тратится на чтение данных. Экономия от использования отображения памяти происходит от того, что нет необходимости копировать данные после их загрузки в ОЗУ. (При использовании других механизмов чтения файлов функция чтения будет копировать данные в предоставленный буфер, где при отображении в памяти файла файл будет помещен прямо в правильное место).

3

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

Вы должны быть в состоянии сделать это, используя что-то вроде:

std::ifstream file(filename_xml.c_str());
char buffer[1024*1024];
file.rdbuf()->pubsetbuf(buffer, 1024*1024);

uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
m_numLines++;
}

Смотрите этот вопрос для получения дополнительной информации:

Как заставить IOStream работать лучше?

0

Так как это окна, вы можете использовать встроенные функции файлов Windows с суффиксом «ex»:

функции управления файлами Windows

в частности, такие функции, как GetFileSizeEx (), SetFilePointerEx (), …. Функции чтения и записи ограничены 32-битным числом байтов, а функции чтения и записи «ex» предназначены для асинхронного ввода-вывода, а не для обработки больших файлов.

0
По вопросам рекламы [email protected]