В следующем случае, какой из них лучше? fread() или mmap()?

Я хочу прочитать два файла через процесс, первый файл около 2G, второй файл около 20M. Они выглядят так:

1   1217907
1   1217908
1   1517737
1   2
1   3
1   4
1   5

Теперь я планирую прочитать весь файл в память, а затем использовать strtok_r() чтобы получить значение каждого числа и сохранить их в массиве структуры данных. 4 процесса могут читать эти два файла на одном компьютере практически одновременно. Компьютер 64-битный, физическая память может быть 4G или даже меньше. У меня вопрос, какой метод является более эффективным? fread() или же mmap()?

Вот ключевая часть моей программы чтения всего файла (поскольку кто-то хочет его увидеть, но я не знаю, связано ли это с моим вопросом):

typedef struct My_Edge
{
int first;
int second;
}Edge;

Edge *myEdge;

int Read_Whole_File()
{

fseek(wholeFile, 0, SEEK_END);

long int fileSize=ftell(wholeFile);

char *buffer=malloc(sizeof(char)*fileSize+1);

fseek(wholeFile, 0, SEEK_SET);

fread(buffer, 1, fileSize, wholeFile);

char *string_first;
char *string_second;
char *save_ptr;

int temp_first;
int temp_second;

string_first = strtok_r(buffer, " \t\n", &save_ptr);
int i=0;

int temp_edge_num;
Edge *temp_edge;

while (string_first != NULL)
{
    temp_first = atoi(string_first);

    string_second = strtok_r(NULL," \t\n",&save_ptr);

    temp_second = atoi(string_second);

    if(i>=my_edge_num)
    {
        temp_edge_num = i + EDGE_NUM_ADJUST;

        temp_edge = realloc(myEdge, sizeof(Edge)*temp_edge_num);
        if(temp_edge)
        {
            myEdge = temp_edge;
        }
        my_edge_num = temp_edge_num;

    }

    if((p_id[temp_first]==*partitionID)||(p_id[temp_second]==*partitionID))
    {
        myEdge[i].first=temp_first;
        myEdge[i].second=temp_second;
        i++;
    }

    string_first = strtok_r(NULL, " \t\n", &save_ptr);

}

return 0;
}

Сейчас я пытаюсь использовать mmap(), но у меня есть EXC_BAD_ACCESS, когда я использую strtok_r() ТП обработать переменную, которая обрабатывается mmap():

символ * буфер;

struct stat fileStat;

fstat(wholeFile, &fileStat);

buffer = mmap(NULL, fileStat.st_size, PROT_READ, MAP_SHARED, wholeFile, 0);

char *string_first;
char *string_second;
char *save_ptr;

int temp_first;
int temp_second;

string_first = strtok_r(buffer, " \t\n", &save_ptr);//EXC_BAD_ACCESS here, the content of buffer is correct.

1 ответ

Решение

У меня вопрос, какой метод является более эффективным? fread() или mmap()?

Прежде всего, давайте посмотрим, как fread и mmap работают на Linux:
fread:
Допустим, мы работаем с файловой системой ext4 (без шифрования), fread использует некоторый внутренний буфер и, если в нем нет данных,
это вызывает read, read выполнить "системный вызов" и через некоторое время мы переходим к:
fs / read_write.c:: vfs_read и после дополнительной работы мы достигаем mm/filemap.c::generic_file_read_iter

И в этой функции мы заполняем кэш страницы inode и читаем данные кеша этой страницы.

Таким образом, мы делаем то же самое, что и "mmap".

Разница что то в fread если мы не работаем напрямую со страницами, мы просто копируем часть данных из кэша страниц inode ядра в буфер пространства пользователя,
в mmap у нас есть кеш страниц прямо в памяти программы. Плюс в fread когда нет страницы в "кеше страницы inode", мы просто читаем ее, но в mmap что вызывает "ошибку страницы", и только после этого мы ее читаем.

Оба варианта используют стратегию "прочитай страницы впереди". Возможная разница может быть в политике "кеша", мы можем контролировать ее в случае "mmap" с madvise и флаги mmap,

Поэтому я полагаю, что ответ "они почти одинаковы по скорости в последовательном чтении, как у вас".

Другие вопросы по тегам