为什么我的系统调用的“猫”function比Linux的“猫”慢?

我已经在C中使用系统调用(open,read和write)来完成这个函数来模拟Linux系统中的“cat”函数,并且它比真实的要慢。

我正在使用与真正的“猫”相同的缓冲区大小,并使用“strace”我认为这是相同数量的系统调用。 但是我的“猫”的输出比真正的“猫”慢了一点。

这是我有的代码:

#define BUFSIZ 32768 int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) { ssize_t writtenBytes = 0; while(writtenBytes < readBytes) { writtenBytes += write(fdout, buffer + writtenBytes, readBytes - writtenBytes); if(writtenBytes == -1) { return -1; } } return 0; } int catPrint(int fdin, int fdout) { char buffer[BUFSIZ]; ssize_t readBytes; do { readBytes = read(fdin, buffer, BUFSIZ); if(readBytes == -1) { return -1; } if(sysWriteBuffer(fdout, buffer, readBytes) == -1) { return -1; } } while(readBytes > 0); return 0; } 

我正在从一个文件中读取(我作为parameter passing给main,我认为这里不需要代码)比我用该文件描述符调用catPrint()函数,输出描述符为1,所以它打印到标准输出。

我不明白为什么它比较慢,因为我正在使用相同的文件进行testing,而对于这两个文件(真正的“猫”和我的),只有一个read()和一个write()用于整个文本。 整个文本不应该出现在屏幕上吗?

PS:我已经把这个标记为家庭作业,虽然我的问题在这里(为什么比较慢)不是作业的一部分。 我只需要使用系统调用来创build一个“猫”types的function,这是完成的。 我只是对我的代码感兴趣,这有点慢。

问题解决从我的瞌睡:
我只是决定在同一个文件中一次又一次地调用linux原来的猫,而且我只是意识到,在我调用它的一些时候,速度也很慢,就像我自己的一样慢。 我想一切都好…

对不起,浪费你的时间就像这样的人。

啊,根据你的编辑,你被readahead缓冲区咬住了。 您无法通过运行一次来​​测试两个并排读取文件的程序。 第一个文件在磁盘上总是比较慢,一旦文件在内存中,第二个将会运行得更快,你必须为每个文件创建新的数据或者运行一个,然后运行它们,这样它们都可以得到readahead缓冲区的好处。

研究mmap(2)。

你将会丢掉ftell / fread,但是如果读取吞吐量真的很重要的话,它会跳过一层间接寻址。

也许你编译没有优化(或没有一样高的优化设置)?

此外,你的代码将调用sysWriteBuffer一次readBytes等于零 – 也许(部分)解释它?

你也可以内联sysWriteBuffer(通过编译器开关或手动)。

“内联”是指将函数的主体复制到其调用地点,以消除调用函数的开销。 有时编译器会自动执行此操作(我认为-O3在gcc中启用了此优化)。 你也可以使用gcc中的inline关键字来告诉编译器内联一个函数。 如果你这样做,你的声明将如下所示:

 static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) { .... 

在不比较源代码的情况下,很难说。 如果您将您的猫与GNU猫进行比较,请记住您正在比较几个小时/天的代码与进化了二十多年的代码。

您可能需要进行更全面的性能分析,从不同的设备(RAM磁盘将是好的)和连续多次运行具有不同输入大小的两个程序。 您必须尝试确定您的程序中的哪个部分比较慢。

由于猫本身是微不足道的(你在评论中说你已经在优化编译),我敢打赌,你所观察到的性能影响并不在实际算法中,而是在程序加载时间上。 如果系统二进制文件是预先链接的 (这在目前大多数发行版中都是常见的),那么您会看到它的加载速度比您自己编译的任何程序都要快(直到包含您的程序预链接)。

多少? 规范的猫是类似的东西

 char bufr[BUFSIZ]; ssize_t len; while((len=read(fdin, bufr, BUFSIZ)) >0) write(fdout, bufr, len); 

这节省了一些指示。

你有没有把两者比较? 您可以尝试使用-tt参数,以便获取系统调用的时间。