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

Ruby 使用函数实时计算结果或直接从数据库读取结果,哪个更有效?,ruby,performance,image-processing,processing-efficiency,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:从数据库获取函数结果 我们有一

让我们以这个场景为例:

存在一个非常复杂的函数,它涉及数学平方根和立方根(处理速度较慢)来计算其输出。例如,假设函数接受两个参数ab,并且值a和b的输入范围定义良好。假设输入值ab的范围为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这样的应用程序为例—处理用户发送到服务器的图像所需的时间以及返回处理后的图像所需的时间必须保持最小,以获得最佳的用户体验。在这种情况下,重要的是尽量减少处理图像所需的时间。更糟糕的是,当此类处理请求的数量越来越多时,就会出现可伸缩性问题

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

有关我的情况的更多详细信息(如果需要):


框架:RubyonRails,数据库:MongodB

我不提倡这两种方法,我会对它们进行测试(如果我认为它们都合理的话)并获得一些数据


写了这篇文章之后,我将开始下圈套:考虑到计算相对于I/O的相对速度,我希望计算比从数据库检索函数值更快。我承认,在某些特殊情况下,内存中的数据库可能会优于(重新)计算,但作为一般规则,如果输入是固定值,则计算结果和从表中读取可能是一个很好的解决方案。如果输入在不同的情况下发生变化,计算最佳时间的实时和缓存结果可能是一个很好的解决方案

“我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源”Donald Knuth

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

如果您谈论的是SQL数据库表中的几百万行,那么选择一行可能比计算结果快得多。在商品硬件上,使用未调优的服务器,我通常可以在十分之几毫秒内从包含数百万行的索引表中返回一行。但在安装dbms服务器并仅为这一目的构建数据库之前,我会仔细考虑

为了让“更快”更具体一点,当你谈论用户体验时,在一定的范围内,实际速度不如表面速度重要。在适当的时间提供适当的反馈会让人们觉得事情进展得很快,或者至少让他们觉得等待一点点并不是什么大事。有关如何实现这一点的详细信息,我将查看Stack Exchange网络

好的是,这两种方法都很简单。对于这个特定问题的速度测试,您甚至不需要在数据库中存储正确的值。您只需要拥有正确的键和索引。如果计算正确的值需要花费一整天的时间,我会考虑这样做。
您可能应该在一段较长的时间内进行测试。我希望dbms的速度会有更多的变化。我不知道你应该期待多少变化。

< P>我会考虑使用散列作为计算和存储的组合。使用表示为
a**b
的非常复杂的函数:

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

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

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

虽然这是一个好主意,但它的实际实现也存在一些问题——如果a和b的值都在0到100之间,那么将fn(a,b)的所有值绘制为数组或散列绝非易事——100x100=10000个数组元素。这种方法很容易造成代码可读性问题。不过,谢谢你的建议@谢谢你的回复。我正在考虑制作一个代码生成器,用数组的sintax将真正的
fn(a,b)
保存到一个文本文件中(而不是手动键入10000个不同的值!!!)。虽然可读性会很差,我同意,但我会将这段代码放在另一个文件中,该文件可以加载
require
,因为在Ruby中,我们可以在其他地方重新打开一个类来更改它谢谢你提供的信息,我以前真的不知道这件事。干杯谢谢,这是一个很好的主意,但在我的情况下,我想这是行不通的-对于每个请求,这个散列将被重置。谢谢你的建议!谢谢,我真的很喜欢这句话:)谢谢你关于速度的细节……肯定有帮助!!谢谢你,非常精确