Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么read()比getc()慢_C++_C_Linux_Unix - Fatal编程技术网

C++ 为什么read()比getc()慢

C++ 为什么read()比getc()慢,c++,c,linux,unix,C++,C,Linux,Unix,为什么syscall read()比getc()函数慢 for (;;) { chr++; amr=read(file1, &wc1, 1); amr2=read(file2, &wc2, 1); if (wc1 == wc2) { if (wc1 == '\n') line++; if (amr == 0) {

为什么syscall read()比getc()函数慢

for (;;) {
        chr++;
        amr=read(file1, &wc1, 1);
        amr2=read(file2, &wc2, 1);
        if (wc1 == wc2) {
            if (wc1 == '\n')
                line++;
            if (amr == 0) {
                if (eflg)
                    return (1);
                return (0);
            }
            continue;
        }
慢于

for (;;) {
    chr++;
    c1 = getc(file1);
    c2 = getc(file2);
    if (c1 == c2) {
        if (c1 == '\n')
            line++;
        if (c1 == EOF) {
            if (eflg)
                return (1);
            return (0);
        }
        continue;
    }
当getc()调用时,它使用read()系统调用,那么为什么较慢呢?

read()
涉及到上下文切换到内核,这相对较慢。当您直接使用它并一次读取一个字节时,您有许多上下文开关。但是当您使用
getc()
时,它将调用
read()
一次,持续4或8 kB,然后从中返回字符,而不进行进一步的上下文切换,直到耗尽缓冲区

如果将
read()
与更大的缓冲区一起使用,它将比
getc()
更快,因为标准C库的通用缓冲有一些开销

(编辑)注意,对于所有常用的存储介质,只能在512字节的块中读取磁盘。所以内核中必须有一些缓冲。而且由于内存是以4096字节的页面分配的,所以大多数系统(Linux肯定会这样做)对物理存储的每个请求至少读取这么多的内存。但是上下文切换也很昂贵,因此userland中额外的缓冲层仍然可以节省大量时间。这种缓冲用于所有的libc IO,它包括使用
文件*
的所有内容(缓冲区是
文件
结构的一部分),因此
fread()
对于小型读取将比
read()
更快。

回答#1:它并不慢

答案2:视情况而定

您不希望对从文件中读取的每个字节进行系统调用(包括内存保护系统上的上下文切换)。在第一个字节大小的访问中,您会将适当数量的数据(比如4k)读入内存,并将第一个字节提供给调用者。在后续字节大小的读取中,您根本不需要调用内核或实际访问文件;您只需从缓冲区传递下一个字节,直到必须读取另一个4k块为止

默认情况下,标准C库的调用(
fread()
fgets()
fgets()
等)就是这样做的。您可以选中
BUFSIZ
以获取默认缓冲区大小。您可以通过
setvbuf()
调用更改缓冲区大小或完全禁用缓冲

read()
不是标准C库的一部分,它是一个POSIX系统调用。基本上,它是POSIX系统上标准C库调用的后端。(在Windows系统上,
fgetc()
将调用Win32 API。)因此,
read()
不缓冲,为字节大小的块调用它效率非常低。如果调用
read()
,通常这样做是因为您希望自己进行缓冲


一般来说,不要混合使用POSIX和标准库I/O调用。使用POSIX API进行低级访问,使用标准库进行便携方便(以及良好的默认性能)。

您是如何确定它的速度较慢的?因为在包含7 878 999个字符(字节)的getc()代码的文件中,不使用缓冲区可以以3倍的速度工作faster@NatKup缓冲区是存储字符的临时位置。假设您的缓冲区有1000个字符,那么对getc的第一个调用读取1000个字符并用它们填充缓冲区。接下来对getc的999调用不进行任何读取,它们只从缓冲区中获取一个字符,因此速度非常快。然后,对getc的第1001次调用将再次填充缓冲区,因此它会重复。