【问题标题】:When does it make sense to store the result of a comparison versus recalculating a comparison in terms of speed?什么时候存储比较结果而不是根据速度重新计算比较?
【发布时间】:2013-03-08 02:38:17
【问题描述】:

我想深入了解何时(忽略可用内存空间)存储比较结果而不是重新计算它是有意义的。证明存储所产生的时间成本合理的临界点是什么?是 2 次、3 次还是 4 次比较?更多?

例如,在这种特殊情况下,哪个选项(通常)在速度方面表现更好?

选项 1:

int result = id.compareTo(node.id);

return result > 0 ? 1 : result < 0 ? -1 : 0;

选项 2:

return id.compareTo(node.id) > 0 ? 1 : id.compareTo(node.id) < 0 ? -1 : 0;

我试图自己分析这两个选项以回答我自己的问题,但我对这种性能测试没有太多经验,因此,我宁愿从有更多的人那里得到更明确的答案经验或更好地掌握所涉及的理论要素。

我知道这没什么大不了的,而且大多数时候差异可以忽略不计。不过,我是一个完美主义者,我真的很想解决这个特殊的问题,这样我就可以继续我的生活了,哈哈。

此外,我认为对于我将来可能遇到的类似情况,我认为答案可能会很有启发性,其中差异可能非常显着(例如,当比较或内存分配的成本无法达到时)发生或复杂到足以导致与性能有关的实际问题)。

请回答与 Java 编程相关的问题,而不是其他语言。

我知道我已经提到过几次了,但请只关注速度差异的答案!我很清楚在编写代码时可以而且应该考虑许多其他因素,但在这里我只想要一个直截了当的论点,即 FASTER。

【问题讨论】:

  • 先考虑可读性,再考虑性能!
  • @ewernli 没错,但我正在寻找的答案实际上只针对一个优先事项:性能。我知道,在实际应用中,我当然会考虑其他(可以说更重要的)优先事项。不过谢谢提醒!
  • 您仍然可以尝试测量执行时间,调用测试方法一百万次,使用 nanoTime() 进行测量,并使用这两种方法的 100 万次调用来预热他的虚拟机。看看方法没有被优化掉:把每个方法调用的结果加起来,最后打印出来。

标签: java performance memory-management comparison processing-efficiency


【解决方案1】:

什么时候存储比较结果而不是根据速度重新计算比较?

大多数情况下,选项 #1 与选项 #2 之类的微优化不会产生任何显着差异。事实上,只有在以下情况下才会产生显着的性能差异:

  • 比较昂贵,
  • 比较执行了很多次,AND
  • 性能很重要。

确实,您已经花费了更多的时间和金钱考虑,而不是在应用程序的整个有用生命周期中节省下来的时间和金钱。

您不应专注于性能,而应专注于使您的代码具有可读性。想想下一个必须阅读和修改代码的人,并让他/她不太可能误读。

在这种情况下,第一个选项比第二个选项更具可读性。这就是您应该使用它的原因,而不是性能原因。 (不过,如果有的话,第一个版本可能更快。)

【讨论】:

  • 最后一句不完整
  • 对不起,但问题很清楚地要求速度比较,而不是与其他问题相关的任何建议或信息。我只是想要一个基于逻辑的理论答案,或者一个基于数学的实验答案,而不是关于在编写代码时考虑其他因素的重要性的讲座(我已经很清楚了)。再次感谢您的关注,但您的回答在这种非常特殊的情况下并不合适。
  • @sweetname:没有逻辑或数学答案。你能得到的最接近的方法是尝试它,要么研究抖动产生的汇编语言,要么在像 kachegrind 这样的循环级解释器下运行它。我所做的是在一个真实的程序中运行它(不管是什么语言),如果一些随机停顿在那里捕捉到它,修复它。
【解决方案2】:

经验告诉我选项 1 应该更快,因为您只需调用 compare 方法并存储结果以供重用。支持这种观点的事实是,局部变量存在于堆栈中,并且进行方法调用涉及堆栈中的更多工作,而不仅仅是将值压入堆栈。然而,分析是比较两种实现的最好和最安全的方法。

首先要意识到的是,java 编译器和 JVM 可以一起优化您的代码,使其希望以最有效的方式完成工作(只要遵循某些规则)。很可能在性能上没有差异,也很可能实际执行的不是你想象的那样。 然而,一个真正重要的区别在于调试:如果您在变量存储版本的返回语句上放置一个断点,您可以看到调用返回的内容,否则在调试器中看不到。更方便的是,当您看似无用地将要从方法返回的值存储在变量中,然后将其返回,这样您就可以在调试时看到方法将返回什么,否则无法看到它。

【讨论】:

  • 您能解释一下“变量中的变量版本”是什么意思吗?如果这是一个愚蠢的问题,我深表歉意,但我无法通过快速的谷歌搜索找到任何可以定义该术语的内容。另外,您是否愿意在您的回答中探讨为什么会出现这种情况?
  • 这是一个错字 - 我已经编辑了我的答案以更正它(我在看电视时在 iPhone 上输入这个:))
  • 在这种情况下,如果您除了提供的其他有用信息之外,还包含与哪个选项在速度方面更好的论点,我将很乐意接受此答案并投票!如果您仍然认为隐藏的编译器实现细节会混淆问题,那么只需说出哪个选项最好假设一个完全愚蠢的编译器“简单地”逐字翻译代码。 :)
  • 您必须始终测量。优化不是猜谜游戏。
  • 我已经给出了我对在我编辑的答案中哪个选项应该表现更好的看法。我还建议阅读并关注亚历克斯对您的问题的评论。
【解决方案3】:

选项 1 不能比 2 慢,如果编译器进行优化,那么两者可能相等,但仍然 1) 更具可读性、更紧凑且可测试性更好。

所以选项 2) 没有论据。

如果您愿意,可以更改为final int result = .... 虽然我希望编译器非常聪明,以至于 final 关键字在这种情况下没有任何区别,并且 final 使代码的可读性降低了一些。

【讨论】:

  • 有趣,我没有考虑使用 final 关键字。您能否进一步解释一下预期的优化(尽管可能没有必要)?
  • 查看java文档会发现final局部变量只能赋值一次,以后就不能再改变了。 java 这样做的目的是为编译器提供更好优化的提示。 (但根据编译器的不同,它可能会分析该变量不再更改,并将其视为您已明确将其定义为 final)
【解决方案4】:

option1总是首选一个,因为这里是真实世界的场景

----->好吧让

1) id.compareTo(node.id) > 0 处的线程执行? 1、在这个进程中还有一些其他线程

id.compareTo(node.id) &gt; 0 ? 1之后更改node.id的值

id.compareTo(node.id) &lt; 0 ? -1 : 0这个检查,结果不一样?

性能明智的选项 1 在检查中存在一些功能时具有更高的性能。

【讨论】:

  • 您能否编辑您的语法和拼写答案以使其更清晰一些?我想我知道你要去哪里了,但话又说回来......鉴于上述困难,我不确定我是否确实这样做了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 1970-01-01
  • 2016-08-20
相关资源
最近更新 更多