什么时候计算或变量读数更快?

时间:2010-03-16 12:22:50

标签: programming-languages performance

说实话,我真的不知道我的cpu和编译器中的“小绿人”是做什么的,所以我有时想知道:)。

目前我想知道什么更快,以便我可以更有效地设计我的代码。 因此,例如,我想在源代码中的不同点处对某些内容进行计算,何时将其计算得更快并将其存储在一个变量中,该变量将被读取并用于下一个需要的点,何时每次计算它的速度更快?

我认为这取决于计算的“复杂”和“长”程度以及缓存的速度,存储变量的速度有多快,但我不知道什么更快:)。

感谢您回复我这个微小而重要的问题!

安德烈亚斯

PS:也许重要的是要知道我在JAVA中编码,但这更像是一个普遍的问题。

9 个答案:

答案 0 :(得分:9)

通常总是更快地存储一次计算的东西,而不是每次计算它。

但是根据计算的复杂程度,它可能无关紧要。例如,如果你想计算3,2和1的总和,那么从计算一次并每次计算它的速度增加将是最小的并且不值得麻烦,除非你做了数百万次。

然而,作为一个对应点,我有一个文件中前5000万个素数的列表,搜索该文件肯定比使用数学方法检查其中一个大数是素数更快。

您应首先编写代码以获取功能和可读性,并且只在遇到问题时担心性能。

答案 1 :(得分:3)

我能想到的唯一一次,它会自动变慢,如果你将值存储在一个文件或一个表(例如数据库)中。然后它可能检索它比重新计算它更慢。这似乎不适用于您的情况,但您说这是一个普遍的问题。

但是你似乎在围绕另一个问题跳舞 - 使用大量全局存储的值是否更好。如果这是你问题的一部分,那么我的答案根本就没有解决。

答案 2 :(得分:1)

这个问题没有真正的答案。如果缓存访问比计算更快,则将内容存储在缓存中会更快。如果缓存访问速度慢于计算速度,则计算速度会更快。

与所有“哪个更快”的问题一样,答案是分析,然后再次分析,然后再次分析。你的计算真的是瓶颈,还是你在某处等待I / O?尝试一下,看看!

答案 3 :(得分:1)

一般情况下,您应该编写最易读和可维护的内容,并且只有在您开始工作后才开始查看性能并发现它太慢了。没有必要优化运行得很好的东西。

由于计算一次并保存结果更易于维护(如果计算更改,您只需要将其更改一个位置),您应该这样做。在代码中重复自己很糟糕。

你会发现这样做也更快。我无法想到任何明显的情况,与重新计算相比,检索预先计算的结果至少不会那么快。

答案 4 :(得分:1)

检索重新计算应该更快,但是你可能会因为在没有任何仪器/测量的情况下决定使用不同的技术而导致过早的微观优化,这会产生任何差异。

答案 5 :(得分:1)

一般来说,在这很重要的情况下,编译器足够智能,可以自己查看。我在谈论潜伏在JVM中的JIT编译器。已知该编译器能够内联方法调用等。

此外,一般建议是编写 clear 代码,并在以下情况下担心此类低级优化:

  • 代码是正确的(它产生了预期的结果);
  • 存在一个实际的,可衡量的绩效问题;
  • 算法很好(例如,你没有使用二次排序或类似的东西)。

此时,你拥有了衡量使用中间变量的影响所需的一切,这很好,因为你的问题的答案一般都是:“好吧,它取决于“。

答案 6 :(得分:0)

我会说计算一次并存储在其中。

在上面的示例中,您不希望一直添加静态值。您将要计算的值很可能是存储在内存/磁盘上的其他变量。

所以,如果你

  1. 收集所有变量
  2. 计算结果
  3. 将其存储在内存中
  4. 从现在开始,您只需要检索值,而不是重复步骤1和2.

答案 7 :(得分:0)

对于任何甚至有些复杂的计算来说,缓存通常都会更快,但需要进行权衡。通过缓存计算结果,当计算结果不再准确时,您必须对使缓存无效负责。请看以下示例:

public class Rectangle
    private int _height;
    public int getHeight() {
        return _height;
    }
    public void setHeight(int value) {
        _height = value;
    }

    private int _width;
    public int getWidth() {
        return _width;
    }
    public void setWidth(int value) {
        _width = value;
    }

    private int _area;
    public int getArea() {
        if (_area == 0) {
            _area = _width * height;
        }
        return _area;
    }
}

这里,区域计算被存储,因此不需要重新计算(这是一个简单的例子,并且乘法不足以证明缓存的合理性,但是你得到了漂移。)。以下代码工作正常:

Rectangle r = new Rectangle();
r.setHeight(5);
r.setWidth(5);

r.getArea(); // returns 25.

但是如果我们修改用于计算缓存项的任何信息,代码就会出现错误:

r.setHeight(3);
r.getArea(); // returns 25 - should be 15!

在这种情况下,解决方案很简单 - 只要设置了高度或宽度,就可以重置区域。但是如果你的计算变得更复杂,计算依赖于单个类之外的某些东西,或者你的缓存机制比简单的成员变量更复杂,那么管理你的缓存会变得有些麻烦。

通常,每当您决定要使用缓存时,都应该谨慎行事并进行大量单元测试,以确保不会引入错误。

答案 8 :(得分:0)

我的两分钱。我在用网络媒体思考。计算所需要的服务器空间或数据传输不只是方程式本身,它还可以包含潜在的无限数量的数字(例如固定规则,例如6的因数)

请注意:顺便说一下,我自己不是编码人员。所以,这可能完全是累了:)