3

次のシナリオを考えてみましょう。配列に入れてjsonに変換する必要のある大きなハッシュがかなりあります。

hash1 = { ... big hash ... }
hash2 = { ... big hash ... }
hash3 = { ... big hash ... }
array = [hash1, hash2, hash3]

json = JSON.dump(array)

問題は、それらのハッシュからjsonを生成するのに時間がかかることです。そのため、キャッシュしたいと思います。ただし、配列全体をキャッシュすることはできず、個別のアイテムのみをキャッシュできます。明らかに、キャッシュされたjson文字列を配列に入れると悪い結果になります:

hash1 = {:a => 1}
hash1json = JSON.dump(hash1)
array = [hash1json]
JSON.generate(array)
==> ["{\"a\":1}"]

私が必要な間

==> [{"a":1}]

私が考えることができる唯一の方法は、次のようなことをすることです。

"[#{[hash1json].join(",")}]"
==> [{"a":1}]

この特定のケースではこれで十分かもしれませんが、単純な配列ではなく深層構造をキャッシュしたい場合は、はるかに困難になります。

4

2 に答える 2

2

これは実際には非常に単純であることがわかります。

class CachedJson
  def initialize(str)
    @str = str
  end

  def to_json
    @str
  end
end

puts Yajl::Encoder.encode(:data => [{:a => 1}, '{"b":2}'])
# => {"data":[{"a":1},"{\"b\":2}"]}

puts Yajl::Encoder.encode(:data => [{:a => 1}, CachedJson.new('{"b":2}')])
# => {"data":[{"a":1},{"b":2}]}

内部では、すべてのオブジェクトでyajl が呼び出さto_jsonれ、このメソッドは文字列を返す必要があるため、キャッシュされた json 文字列をCachedJsonオブジェクトでラップするだけです。

于 2013-04-23T22:37:35.103 に答える
0

編集

私の以前の回答は、質問のパフォーマンスの側面を完全に見逃していたので(申し訳ありません)、これが私の発見です。おそらくそれはあなたを少し助けることができます。

どうやらこれらの状況では、 yajl ライブラリーyajl-rubyへのバインディングである を使用すると、変換中のパフォーマンスが向上するようです。Cたとえば、ここでは10,000エントリを使用してハッシュを生成しています。

  require 'json'
  require 'yajl'
  require 'benchmark'
  tmp = "" 
  10000.times do |i|
   tmp += "\"#{i}\" => \"#{i}\", " 
  end

 domains = eval("{#{tmp}}")

 puts "JSON DUMP #{Benchmark.measure { JSON.dump(domains) }} "

 puts "Yajl::Encoder #{Benchmark.measure { Yajl::Encoder.encode(domains)}}"

そして、これらは結果です:

JSON DUMP   0.010000   0.000000   0.010000 (  0.007495)

Yajl::Encoder   0.000000   0.000000   0.000000 (  0.003542)

一貫して、json に変換するタスクの時間を半分にしています。それが役に立てば幸い!

于 2013-03-07T21:03:04.747 に答える