为什么我的“猫”是 与 Linux 的“cat”相比,系统调用速度更慢的函数?

发布于 2024-07-17 05:09:46 字数 1361 浏览 7 评论 0原文

我已经在 C 中使用系统调用(打开、读取和写入)来模拟 Linux 系统中的“cat”函数来完成此函数,并且它比真实的函数慢......

我使用与真实的缓冲区大小相同的“ 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;
}

我正在从一个文件中读取(我将其作为参数传递给 main,我认为这里不需要代码),然后使用该文件描述符调用 catPrint() 函数,并使用 1 作为输出描述符所以它打印到标准输出。

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

PS:我已将其标记为家庭作业,尽管我在这里的问题(为什么速度较慢)不是家庭作业的一部分。 我只需要使用系统调用来创建一个“cat”类型的函数,这就完成了。 我只是对我的代码感兴趣,它有点慢。

我愚蠢地解决了问题:
我只是决定在同一个文件上调用linux的原始cat几次,一个接一个,我刚刚意识到有时我调用它的时候它也很慢,就像我自己的一样慢。 我想一切都很好......

很抱歉像这些人一样浪费了您的时间。

I've done this function in C using system calls (open, read and write) to simulate the "cat" function in Linux systems and it's slower than the real one...

I'm using the same buffer size as the real "cat" and using "strace" I think it's making the same amount of system calls. But the output from my "cat" is a little bit slower than the real "cat".

This is the code I have:

#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;
}

I'm reading from a file (that I pass as argument to main, I think that code is not needed here) than I call the catPrint() function with that file descriptor and 1 for the output descriptor so it prints to stdout.

I don't understand why it's slower because I'm using the same file for testing and with both (the real "cat" and mine) there's only one read() and one write() for the whole text. Shouldn't the whole text just appear on screen?

P.S: I've tagged this as homework although my question here (why it's slower) is not part of the homework. I only needed to use the system calls to create a "cat" type function, which is done. I'm just intrigued by my code that's a bit a slower.

PROBLEM SOLVED WITH STUPIDITY FROM ME:
I just decided to call linux's original cat a few times on the same file, one after the other, and I just realized that it was also slow some of the times I called it, just as slow as my own. I guess everything's fine than...

Sorry for wasting your time like this people.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吻风 2024-07-24 05:09:46

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

Ah, based on your edit you were being bitten by the readahead buffer. You cannot test two programs that read files side by side by running them once. The first always be slower since the file is on disk, once the file is in memory the second will run faster, you must either create new data for each or run one and then run both so they both get the benefit of the readahead buffer.

隱形的亼 2024-07-24 05:09:46

研究 mmap(2)。

您将抛弃 ftell/fread 的细节,但如果读取吞吐量确实很重要,它将跳过间接层。

Research mmap(2).

You will be throwing aways niceties of ftell/fread, but it will skip a layer of indirection if read throughput is really important.

最佳男配角 2024-07-24 05:09:46

也许您在没有优化的情况下编译(或者没有那么高的优化设置)?

另外,您的代码将在 readBytes 等于零的情况下调用 sysWriteBuffer 一次 - 也许这(部分)解释了这一点?

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

"内联" 表示将函数体复制到其调用站点以删除调用函数的开销。 有时编译器会自动执行此操作(我认为 -O3 在 gcc 中启用了此优化)。 您还可以在 gcc 中使用 inline 关键字 告诉编译器内联函数。 如果您这样做,您的声明将如下所示:

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

Perhaps you compiled without optimization (or without as high an optimization setting)?

Also, your code will call sysWriteBuffer once with readBytes equal to zero -- maybe that (partially) explains it?

You might also inline sysWriteBuffer (either via a compiler switch or by hand).

"inlining" means to copy the body of a function to its call site in order to remove the overhead of calling a function. Sometimes compilers do this automatically (I think -O3 enables this optimization in gcc). You can also use the inline keyword in gcc to tell the compiler to inline a function. If you do this, your declaration will look like this:

static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
....
凤舞天涯 2024-07-24 05:09:46

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

您可能想要进行更全面的性能分析,从不同的设备(RAM 磁盘会很好)以不同的输入大小连续多次运行这两个程序。 您必须尝试确定程序中哪些地方速度较慢。

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

Without comparing the source codes, it is difficult to say. If you are comparing your cat with GNU cat, remember that you are comparing a code that is a few hours/days old with a code that evolved for more than twenty years.

You may want to do a more comprehensive performance analysis, running the both programs with different input sizes, from different devices (a RAM disk would be good) and multiple times in a row. You must try to determine WHERE in your program it is slower.

Since cat itself is really trivial (and you said in a comment that you are already optimizing the compilation), I bet the performance impact you are observing is not in the actual algorithm, but on program load times. If the system binary is prelinked (which is common on most distros nowadays), you will see that it is loaded faster than any program you compile yourself (until you include your programs prelinking).

无声无音无过去 2024-07-24 05:09:46

多少? 规范猫类似于

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

它保存了一些指令。

How much? The canonical cat is something like

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

which saves a few instructions.

扬花落满肩 2024-07-24 05:09:46

您比较过两者的 strace 吗? 您可以尝试使用 -tt 参数来获取系统调用的时间。

Did you compare straces of both? You might try to use the -tt parameter so you get the timing of the syscalls.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文