【问题标题】:Most efficient method to print "test"? [closed]打印“测试”的最有效方法? [关闭]
【发布时间】:2017-07-28 18:24:14
【问题描述】:

在消耗最少资源的同时打印一些东西。

它甚至可以是01 不一定是test

fputs("test",stdout);
printf("%s", "test");
puts("test");

以上哪个命令效率最高?

还有其他更高效的方法吗?

【问题讨论】:

  • 什么样的“资源”(时间、内存……)?
  • 这些功能的内部实现不受任何标准的规范。人们可以随心所欲地实现它们。
  • 您可以直接使用 POSIX 定义的函数 write(),而不是让标准 I/O 库间接使用它。您应该决定是否要在输出末尾添加换行符——puts() 添加它,其他不添加(write() 也不添加)。有一些方法可以解决这个问题,例如使用字符串"test\n" 到更深奥的技术使用writev() 等。但是,在像test 这样短的字符串上,效率是一条红鲱鱼。
  • 我否决了这个问题。你可以很容易地自己测试它。这个问题只是懒惰的一个例子。编写几个测试程序,用不同的编译器编译它们并在不同的操作系统(例如 windows linux)下运行。你在 15 分钟内完成。
  • @Chris Cousins 我们是时候阅读它了

标签: c


【解决方案1】:

这三个备选方案之间的执行时间基本上没有区别,并且一些优化编译器实际上会将printf 转换为对fputs 之类的调用。因此,请选择以您认为最清晰的方式做您想做的事。

请注意puts("test"); 在单词后写一个换行符。如果您想要换行符,那可能是最干净的解决方案。如果您不想要换行符,请使用其他两个之一。

在尝试优化代码时,请着眼于全局。你用的是最好的算法吗?你在做不必要的工作吗?你能使用更好的数据结构吗?相信编写编译器和标准库的人在优化常用习语方面做得很好。他们是优秀的程序员,他们的工作是专注于让您的代码运行得更快的小细节。

【讨论】:

  • 我不同意。 printf 将是最慢的,因为它不仅仅显示字符串。
  • @Bjorn A. 这是一个太宽泛的问题,因为我们有许多编译器、许多标准库实现等。由于评论中解释的原因,我对 OPs 问题投了反对票。我们浪费时间回答和讨论此类问题,Satura 可以自己测试,而不是问。 PS当格式和字符串是文字时,我的gcc 7.1调用printf
  • @PeterJ 我赞成你的反对票。这个问题很愚蠢。顺便说一句,我之前的评论不正确,这就是我删除它的原因。很抱歉造成混乱。
  • @PeterJ 不确定您所说的愚蠢是什么意思,但我确实觉得许多问题可以通过许多 OP 的一点点努力轻松解决。天啊,即使是谷歌也能回答我们这些天得到的大部分 C 问题。只是我的 2 美分...
  • @PeterJ_01 “printf 将是最慢的。”我不同意。 :-) 在我的机器(一台 5 年前的消费级笔记本电脑)上,对于 10,000 次通话,在所有情况下,时间都是相同,精确到小数点后三位。
【解决方案2】:

这里基本上有两个答案。

(1) 就几乎所有实际目的而言,两者在性能(时间或使用的其他资源)方面没有差异

puts("test");
fputs("test\n",stdout);
printf("%s\n", "test");
fprintf(stdout, "%s\n", "test");

(在换行符处理方面存在一些差异,如图所示。)

使用最清晰且对您的程序有意义的一个;不用担心这里的效率。

(2) 任何形式的问题“其中哪一个最快?”只能在特定环境的上下文中回答,一般无法预测。如果您真的很在意,那么除了在您的确切环境中执行经验测试之外,您基本上别无选择。请注意,由于性能差异充其量可能很小(请参阅答案 1),您可能必须执行数千或数百万次测试才能获得具有统计意义的答案 - 这几乎强化了这一点,实际上,任何差异都可能无关紧要。


现在,只是为了好玩,我进行了一个测试。下面是一个小程序,用于测试所有四个备选方案,以及低级 write 系统调用:

#include <stdio.h>
#include <time.h>

int main()
{
    int count = 100000000;
    time_t t1, t2;
    int delta;
    int i;

    t1 = time(NULL);

    for(i = 0; i < count; i++) puts("test");

    t2 = time(NULL);
    delta = (int) t2 - t1;

    fprintf(stderr, "test 1: %d secs (%f prints/sec)\n",
        delta, (double)count/delta);

    t1 = t2;

    for(i = 0; i < count; i++) fputs("test\n", stdout);

    t2 = time(NULL);
    delta = (int) t2 - t1;

    fprintf(stderr, "test 2: %d secs (%f prints/sec)\n",
        delta, (double)count/delta);

    t1 = t2;

    for(i = 0; i < count; i++) printf("%s\n", "test");

    t2 = time(NULL);
    delta = (int) t2 - t1;

    fprintf(stderr, "test 3: %d secs (%f prints/sec)\n",
        delta, (double)count/delta);

    t1 = t2;

    for(i = 0; i < count; i++) fprintf(stdout, "%s\n", "test");

    t2 = time(NULL);
    delta = (int) t2 - t1;

    fprintf(stderr, "test 4: %d secs (%f prints/sec)\n",
        delta, (double)count/delta);

    t1 = t2;

    for(i = 0; i < count; i++) write(1, "test\n", 5);

    t2 = time(NULL);
    delta = (int) t2 - t1;

    fprintf(stderr, "test 5: %d secs (%f prints/sec)\n",
        delta, (double)count/delta);
}

您会注意到我已选择运行每个测试一亿次。 (当我说“您可能需要执行数千或数百万次测试”时,我并不是在开玩笑。)不过,结果如下:

test 1: 9 secs (11111111.111111 prints/sec)
test 2: 8 secs (12500000.000000 prints/sec)
test 3: 17 secs (5882352.941176 prints/sec)
test 4: 16 secs (6250000.000000 prints/sec)
test 5: 45 secs (2222222.222222 prints/sec)

所以,从某种意义上说,我的答案 (1) 是错误的。有一点不同:至少在我的机器上,putsfputs 的速度大约是 printffprintf 的两倍。但是我必须调用它们一亿次才能看到这种差异这一事实表明,在现代机器上,如果你只进行几千万或几百或几千甚至几百万或几千万次调用,你可能根本看不到任何区别。

[附注我的测试程序不是严格可移植的。我应该使用long int 作为柜台。]

【讨论】:

  • write( STDOUT_FILENO, "test\n", 5UL ); 的表现如何?
  • @AndrewHenle 查看代码——这基本上是测试 5。正如我所料,它的速度要慢得多。 stdio 缓冲通常是一种胜利。
  • 啊,我的错。被滚动条弄糊涂了。我真的很惊讶一个简单的write()fprintf( stderr, "%s\n", "test" ); 慢三倍我怀疑那里有某种类型的优化。
  • @AndrewHenle 据我所知,优化称为“缓冲”。像write 这样的系统调用可能很昂贵。 (在当时,它们的成本可能是普通函数调用的 10 到 100 倍。今天还不错。)调用write 一次打印几个字符是一种可怕的浪费。正如我所说,让 stdio 在缓冲区中保存一堆要写入的字符,而不是在缓冲区中调用 write 直到它有 412、1024 或 8192 个字符,这是一个巨大的胜利。
  • @BjornA.同意所有观点。我确实重定向到 /dev/null。但是,如果有什么能让putsfputs 看起来更好,因为如果 i/o 是真实的,实际 i/o 的贡献会更大,并且 (f)puts 与 (f) 之间的差异)printf 相应减少。但另一件事是,如果 OP 担心 i/o 效率,它可能是文件(即完全缓冲),而不是 tty。
猜你喜欢
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 2010-10-19
  • 1970-01-01
相关资源
最近更新 更多