我想通过一个进程读取两个文件,第一个文件大约是2G,第二个文件大约是20M。 它们看起来像这样:
1 1217907
1 1217908
1 1517737
1 2
1 3
1 4
1 5
现在我计划将整个文件读入内存,然后使用strtok_r()
获取每个num的值并将它们存储在数据结构数组中。 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()
,但当我使用strtok_r()
tp处理由mmap()
处理的var时,它有EXC_BAD_ACCESS:
char * buffer;
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.
答案 0 :(得分:1)
我的问题是,哪种方法更有效? fread()或mmap()?
首先,让我们看看fread和mmap如何在linux上运行:
fread
:
让我们说我们使用ext4文件系统(没有加密),
fread使用一些内部缓冲区,如果没有数据,则
它调用read
,read
执行"系统调用"
过了一段时间我们跳到:
FS / read_write.c :: vfs_read
经过更多的工作我们到达
毫米/ filemap.c :: generic_file_read_iter
在这个函数中我们填写inode页面缓存并读取到此
页面缓存数据。
所以我们和" mmap"基本相同。确实
fread
案例中我们没有直接的区别
使用页面,我们只是从内核复制部分数据
inode页面缓存到用户空间缓冲区,
在mmap
我们直接在程序中有页面缓存
记忆空间。当{" inode页面缓存中没有页面"
我们只是阅读它,但在fread
导致"页面错误",
然后我们就读了它。
两种变体都使用"提前读取页面"战略。
可能的差异可能在"缓存"政策,
我们可以在" mmap"中控制它mmap
的案例和madvise
的旗帜。
所以我认为答案是"它们在序列读取速度方面与你的速度几乎相同"。