2012-03-02 11 views
3

は、私たちはこのシナリオ例を見てみましょう:どちらが効率的ですか?リアルタイムで関数を使用して結果を計算するか、結果をデータベースから直接読み取るか?

その出力を計算するために数学的平方根と(プロセスに遅い)立方根を伴う本当に複雑な関数が存在します。例として、関数が2つのパラメータbを受け入れ、値aとbの両方の入力範囲がと定義されているとします。です。私たちは、入力が0からだから、基本的に100

FNの範囲とすることができ aとb値と仮定しましょう(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のようなアプリケーションを作成する例を考えてみましょう。ユーザーがサーバーに送信したイメージを処理するのにかかる時間と、処理されたイメージを返すまでの時間は、最適なユーザー-経験。このような状況では、画像の処理に要する時間を最小限に抑えることが重要です。さらに、このような処理要求の数が増えると、スケーラビリティの問題が発生することになります。

したがって、このような状況でも最も最適な方法である前述の方法の1つを選択する必要があります。状況に関する

詳細(を必要に応じて):

フレームワーク:Railsの上ルビー、データベース: MongoDBの

答えて

2

は「より効率的な」あいまいな用語です。 「より速く」はより具体的です。

SQLデータベーステーブルの数百万行について言えば、結果を計算するよりも単一行を選択するほうが速いかもしれません。コモディティハードウェアでは、未調整のサーバーを使用して、通常、ミリ秒の数十分の1秒でインデックス付きのテーブルから1行を返すことができます。しかし、私はdbmsサーバーをインストールしてこの目的のためだけにデータベースを構築する前に、大変だと思います。

ユーザーエクスペリエンスと特定の制限内で話すときに「より速く」具体的にするために、実際の速度は見かけの速度より重要ではありません。適切なタイミングで適切なフィードバックをすることで、人々は速く走っているように感じるか、少なくとも少し待つような気分になることは大したことではありません。正確に行う方法の詳細については、Stack ExchangeネットワークのUser Experienceを参照してください。

良いことは、両方の方法をテストするのがかなり簡単だということです。この特定の問題のみを速度テストするには、データベースに正しい値を格納する必要はありません。あなたは正しいキーとインデックスを持っているだけです。私は、正しい値を計算するのが終日になるとすれば、そのことを検討したいと思います。

おそらく長期間テストする必要があります。私はdbmからより多くのバリエーションがあると期待しています。しかし、私はあなたが期待すべきどれほどのばらつきも知らない。

+0

ありがとう、私が知りたいと思っていた非常に正確に。また、ユーザーエクスペリエンスのガイドラインの+1は、多くの意味があります。ありがとう!! – dsignr

3

私はどちらかの方法を提唱していないだろう、私は思いますそれらを両方ともテストしてください(両方が合理的だと思ったら)、データを取得してください。

これを書いたので、私は餌になるでしょう:計算と入出力の相対的な速度を考えると、データベースから関数の値を取り出すよりも計算が高速になると思います。いくつかの特殊なケースでは、メモリ内のデータベースが(再)計算を上回る可能性がありますが、一般的なルールではないという可能性を認めます。

+0

おかげで助けました! – dsignr

2

入力を固定値にすると、結果を計算してテーブルから読み込むことは良い解決策になります。最適な時間のリアルタイムおよびキャッシング結果の計算は、さまざまな状況で入力が変化する場合には良い解決策になります。

「我々は小さな効率を忘れなければならない、時間の約97%を言う:時期尚早の最適化は諸悪の根源である」ドナルド・クヌース

+0

ありがとう、私は単に実際にこの引用を愛しています:) – dsignr

0

計算と保存の組み合わせとしてハッシュを使用することを検討します。 a**bとして表さ彼は本当に複雑な機能を:

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

ありがとう、これはきちんとした考えですが、私の場合、これはうまくいかないでしょう - それぞれの要求に対して、このハッシュはリセットされます。しかし、提案をありがとう! – dsignr

0

私は、コード自体に値を格納について考えたい:speed..surelyの詳細については、

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 
+0

これは良い考えですが、実際の実装にはいくつかの問題があります.aとbの両方の値が0から100の範囲にある場合、fn(a、b)のすべての値を配列またはハッシュ簡単なジョークではありません - 100x100 = 10,000の配列要素。コードの読みやすさは、このアプローチでは簡単に問題になる可能性があります。しかしねえ、提案に感謝! – dsignr

+0

@imaginonicご回答いただきありがとうございます。実際の 'fn(a、b)'を配列のsintaxを持つテキストファイルに保存する(手動で10000の異なる値を入力するのではなく!!!)コード生成を行うことを考えていました。読みやすさは恐ろしいものですが、私は同意しますが、Rubyでは他のクラスを再オープンして変更することができるので、 'require'をロードできる別のファイルにそのコードを残しておきます。 :) –

+0

情報をありがとう、私は正直なところこれについて知りませんでした。乾杯! – dsignr

関連する問題