哪个更有效 - 实时使用函数计算结果或直接从数据库读取结果?

时间:2012-03-02 10:50:30

标签: ruby performance image-processing processing-efficiency

让我们来看看这个示例场景:

存在一个真正的复杂函数,它涉及数学平方根和立方根(处理速度较慢)来计算其输出。例如,让我们假设函数接受两个参数 a b ,并且值a和b的输入范围定义良好。我们假设输入值 a b 的范围为0到100。

所以基本上 fn(a,b)可以实时计算,也可以在数据库中预先填写结果,并在需要时提取。

方法1:实时计算

function fn(a,b){

result = compute_using_cuberoots(a,b)

return result
}

方法2:从数据库中获取函数结果

我们有一个数据库预先填充了映射到相应结果的输入值:

a   |  b  | result
0   |  0  |   12.4
1   |  0  |   14.8
2   |  0  |   18.6
.   |  .  |    .
.   |  .  |    .
100 | 100 |  1230.1

我们可以

function fn(a,b){

result = fetch_from_db(a,b)

return result
}

我的问题:

您会提倡哪种方法?为什么?为什么你认为一种方法比另一种更有效?

我相信这是我们大多数人在编程生涯中某个时候会遇到的情况,因此这个问题。

谢谢。

问题背景(可能不相关)

示例:在像图像处理这样的场景中,可能会更频繁地遇到这种情况,其中输入(R,G,B)的值范围是已知的(0- 255)并且平方根和立方根的数学计算为服务器请求的完成带来了太多的时间。

让我们举个例子来构建像Instagram这样的应用程序 - 处理用户发送到服务器的图像所花费的时间以及返回处理过的图像所需的时间必须保持最小化以获得最佳效果用户体验。在这种情况下,最小化处理图像所花费的时间是很重要的。更糟糕的是,当此类处理请求数量增加时,会引入可伸缩性问题。

因此,有必要在上述方法中选择一种在这种情况下也是最佳方法。

my 情况的详细信息(,如果需要):

框架: Ruby on Rails,数据库: MongodB

5 个答案:

答案 0 :(得分:3)

我不提倡任何一种方法,我会测试它们(如果我认为它们都是合理的)并获得一些数据。

编写完之后,我会提到诱饵:考虑到计算与I / O的相对速度,我希望计算比从数据库中检索函数值更快。我将承认在某些特殊情况下内存数据库能够胜过(重新)计算的可能性(并且不再存在),但作为一般规则,没有。

答案 1 :(得分:2)

如果输入是固定值,计算结果和从表中读取可能是一个很好的解决方案。如果输入在不同情况下变化,那么计算实时和缓存结果以获得最佳时间可能是一个很好的解决方案。

  

“我们应该忘记效率低下,大约97%的时间说:过早的优化是所有邪恶的根源” Donald Knuth

答案 2 :(得分:2)

“效率更高”是一个模糊的术语。 “更快”更具体。

如果您在谈论SQL数据库表中的几百万行,那么选择单行可能比计算结果更快。在商用硬件上,使用未调整的服务器,我通常可以在几十分之一毫秒的时间内从数百万行的索引表中返回一行。但是,在安装dbms服务器并仅为此目的构建数据库之前,我会认真思考。

为了使“更快”更具体,当你谈论用户体验时,在一定限度内,实际速度不如表观速度重要。在合适的时间提供正确的反馈会让人感觉事情正在快速发展,或者至少让他们觉得等待一点点并不是什么大问题。有关如何执行此操作的详细信息,请查看Stack Exchange网络上的User Experience

好消息是,测试这两种方式非常简单。对于这个特定问题的速度测试,您甚至不需要在数据库中存储正确的值。您只需拥有正确的密钥和索引即可。如果计算正确的值需要一整天,我会考虑这样做。

你应该在很长一段时间内进行测试。我希望dbms的速度有更多变种。不过,我不知道你应该期待多少变化。

答案 3 :(得分:0)

我会考虑使用哈希作为计算和存储的组合。他的功能非常复杂,表示为a**b

lazy = Hash.new{|h,(a,b)|h[[a,b]] = a**b}
lazy[[4,4]]
p lazy #=> {[4, 4]=>256}

答案 4 :(得分:0)

我考虑将值存储在代码本身上:

class MyCalc
  RESULTS = [
    [12.4, 14.8, 18.6, ...]
    ...
    [..., 1230.1]
  ]
  def self.fn a, b
    RESULTS[a][b]
  end
end

MyCalc.fn(0,1)         #=> 14.8