C 流缓冲问题

C 流缓冲问题,c,C,mod_rewrite声明,严格要求在重写程序中禁用输入(输出)缓冲 记住这一点,我编写了一个简单的程序(我知道它缺少EOF检查,但这不是问题,它为每个循环保存了一个条件检查): 使其速度是Perl的两倍。这不应该影响Apache的性能,是吗 问题2。如何用C语言编写一个使用无缓冲流(如Perl one)并与Perl one一样快的程序?问题1:您必须查看代码。它可以是行缓冲的,可以在每个请求(或请求块)结束时使用fflush,也可以使用具有更大缓冲区的写调用。在任何情况下,它都不会执行程序正在

mod_rewrite声明,严格要求在重写程序中禁用输入(输出)缓冲

记住这一点,我编写了一个简单的程序(我知道它缺少EOF检查,但这不是问题,它为每个循环保存了一个条件检查):

使其速度是Perl的两倍。这不应该影响Apache的性能,是吗


问题2。如何用C语言编写一个使用无缓冲流(如Perl one)并与Perl one一样快的程序?

问题1:您必须查看代码。它可以是行缓冲的,可以在每个请求(或请求块)结束时使用fflush,也可以使用具有更大缓冲区的写调用。在任何情况下,它都不会执行程序正在执行的每字符I/O操作

问题2:我怀疑主要问题在于产出。如果您将整个结果组合到一个缓冲区中,并将其作为一个调用写入,那么您会更快。然而,这仅仅意味着您正在执行行缓冲,而不是让库为您处理它。关键是没有缓冲,每个输出调用都会导致系统调用,这是非常高的开销。理论上,同样的概念在输入上也适用,但我不确定实现是否会注意到可用字符并在任何情况下缓冲它们。同样的解决方法——读取一个更大的缓冲区,然后自己把它拆开


就我个人而言,我会避免所有setvbuf内容,只在每个请求结束时进行fflush。

在向终端写入时,
stdout
会在每行之后刷新。这样,您总是可以立即看到输出。当写入文件或管道时,此自动刷新将被禁用。通常在这些情况下,性能更为重要

当流程必须相互交互时,这会导致问题。一个程序写一些东西。它不会立即发送,而是存储在缓冲区中。第二个程序等待该数据。第一个程序等待来自第二个程序的更多数据,导致死锁

为了避免这种情况,您需要在等待其他输入之前刷新所有输出。在每次
read操作之前,简单的
fflush(stdout)
就足够了。这实际上是Perl中
$|=1
所做的。无需使用
stdin
执行任何操作

如果性能非常关键,您只需要对单个字节进行操作。使用unbuffered/读取和写入大块数据。例如:

#include <unistd.h>

int main() {
    char buf[1024];
    while(1) {
        int len = read(0,buf,sizeof(buf));
        for(int i=0;i<len;i++) {
            if ( buf[i] == '-' ) {
                buf[i] = '_';
            }
        }
        write(1,buf,len);
    }
}
#包括
int main(){
char-buf[1024];
而(1){
int len=read(0,buf,sizeof(buf));

对于(int i=0;i您不应该使用
setvbuf(stdout,NULL,_IONBF,0)
?@FatalError修复了输入错误,谢谢。没有缓冲的程序速度非常慢。但我相信在这种情况下使用缓冲可能没有问题。42s是怎么回事?@DrC 42保持while循环运行的,因为它的计算结果为
true
并且42数百个字节被分配到流缓冲区。但是为什么没有缓冲的Perl script太快了?我不太了解Perl,但我怀疑它实际上并不是无缓冲的。只有一个调用
$|=1;
,它只对一个流禁用缓冲。我认为逐个检查每个字符要比逐块读取字符然后扫描这些块以替换字符更有效。我有问题我可能会弄错……我实际上并不熟悉$|,所以不能说太多关于它的确切语义。我强烈怀疑该脚本正在运行行缓冲,因为它总是读取和写入完整的行。在这种情况下,这一切都与系统调用的数量有关——按行处理的调用要少得多。
#!/usr/bin/perl
    $| = 1; # Turn off I/O buffering
    while (<STDIN>) {
        s/-/_/g; # Replace dashes with underscores
        print $_;
    }
setvbuf(stdin,NULL,_IOLBF,4200);

setvbuf(stdout,NULL,_IOLBF,4200);
#include <unistd.h>

int main() {
    char buf[1024];
    while(1) {
        int len = read(0,buf,sizeof(buf));
        for(int i=0;i<len;i++) {
            if ( buf[i] == '-' ) {
                buf[i] = '_';
            }
        }
        write(1,buf,len);
    }
}