Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

OpenStructがパフォーマンスを低下させる方法

私たちRubyistsは私たちのハッシュが大好きです。しかし、ハッシュにはいくつかのよく知られた欠陥があります。リチャードがHashieConsideredHarmfulで指摘したように、柔軟性が高すぎる場合があります。簡単なタイプミスで、意図していなかったキーを割り当てたり参照したりできます。

a = { type: "F150" }
a[:typo] # nil
いくつかの一般的なハッシュの代替案

ハッシュを使用して実際の構造化データを格納している場合は、実際には柔軟性は必要ないと判断する可能性があります。それはあなたを困らせるだけだということ。

いくつかの選択肢があります。 XY座標のペアを保存する必要があると想像してください。 1つのアプローチは、クラスを定義することかもしれません。その唯一の仕事は、XY座標のペアを保持することです。

class PointClass # I don't recommend ending class names with Class :) 
  attr_accessor :x, :y
  def initialize(args)
    @x = args.fetch(:x)
    @y = args.fetch(:y)
  end
end

point_class = PointClass.new(x: 1, y: 2)
point_class.x # 1

この場合、データをカプセル化するだけでよいので、より簡潔な選択はStructを使用することかもしれません。次のようになります:

PointStruct = Struct.new(:x, :y)

point_struct = PointStruct.new(1, 2)
point_struct.x # 1

3番目のオプションは、OpenStructを使用することです。 OpenStructは構造体のように見えますが、ハッシュのように任意の値を設定できます。次に例を示します:

point_os = OpenStruct.new(x: 1, y: 2)

point_os.x # 1
パフォーマンスへの影響

[2015年7月10日更新:私のベンチマークスクリプトはハッシュに対して不公平だったようです。 Patrick Helmが指摘したように、私はそれらを初期化する非効率的な方法を使用していました。したがって、ハッシュの結果は無視してください。 openstructが非常に遅いという私の主なポイントはまだ有効ですが。ここで私のベンチマークスクリプトに対する彼の変更を見ることができます]

これらの4つのオプションを見て、パフォーマンスへの影響は何かと思い始めました。ほんの少しのデータしか扱っていない場合、これらのオプションのいずれも十分に高速であることは明らかです。ただし、処理するアイテムが数千または数百万ある場合は、ハッシュ、OpenStruct、構造体、クラスのパフォーマンスへの影響が問題になり始める可能性があります。

Honeybadgerでは、毎秒何千もの例外がAPIに報告されているため、このようなパフォーマンスへの影響を理解することは常に私たちの頭の中にあります。

そこで、簡単なベンチマークスクリプトを作成しました。このような実験にはbenchmark-ipsgemを使用するのが好きです。これは、適切なサンプルサイズを自動的に判断し、標準偏差を報告するためです。

初期化

PointClass、PointStruct、Hash、およびOpenStructの初期化時間をベンチマークしたところ、PointClassとPointStructが明らかに勝者であることがわかりました。それらはOpenStructよりも約10倍速く、ハッシュよりも約2倍速かった。

OpenStructがパフォーマンスを低下させる方法

OpenStructがパフォーマンスを低下させる方法 PointClassとPointStructはOpenStructよりもほぼ10倍高速でした

これらの結果は理にかなっています。構造体は最も単純なので、最速です。 OpenStructは最も複雑であるため(Hashのラッパーです)、最も低速です。ただし、速度の違いの大きさは驚くべきものです。

この実験を実行した後、速度が懸念されるコードでOpenStructを使用することを本当に躊躇します。そして、パフォーマンスが重要なコードで見られるハッシュには注意を払うつもりです。

読み取り/書き込み

初期化とは異なり、値の設定とアクセスに関しては、4つのオプションはすべてほぼ同じです。

OpenStructがパフォーマンスを低下させる方法

OpenStructがパフォーマンスを低下させる方法 ベンチマークの読み取りと書き込みは、Struct、クラス、ハッシュ、OpenStructの間に大きな違いはありません

ベンチマークスクリプト

独自のシステムでベンチマークを実行する場合は、以下のスクリプトを使用できます。 OSXのMRI2.1で実行しました。他のルビーインタプリタのパフォーマンスに興味がある場合は、MichaelCohenがMRI2.2、JRubyなどの結果を含む素晴らしい要点を作成しました。

require 'benchmark/ips'
require 'ostruct'

data = { x: 100, y: 200 }

PointStruct = Struct.new(:x, :y)

class PointClass
  attr_accessor :x, :y
  def initialize(args)
    @x = args.fetch(:x)
    @y = args.fetch(:y)
  end
end

puts "\n\nINITIALIZATION =========="

Benchmark.ips do |x|
  x.report("PointStruct") { PointStruct.new(100, 200) }
  x.report("PointClass") { PointClass.new(data) }
  x.report("Hash") { Hash.new.merge(data) }
  x.report("OpenStruct") { OpenStruct.new(data) }
end

puts "\n\nREAD =========="

point_struct = PointStruct.new(100, 200)
point_class = PointClass.new(data)
point_hash = Hash.new.merge(data)
point_open_struct = OpenStruct.new(data)

Benchmark.ips do |x|
  x.report("PointStruct") { point_struct.x }
  x.report("PointClass") {  point_class.x }
  x.report("Hash") { point_hash.fetch(:x) }
  x.report("OpenStruct") {  point_open_struct.x }
end


puts "\n\nWRITE =========="

Benchmark.ips do |x|
  x.report("PointStruct") { point_struct.x = 1 }
  x.report("PointClass") {  point_class.x = 1 }
  x.report("Hash") { point_hash[:x] = 1 }
  x.report("OpenStruct") {  point_open_struct.x = 1 }
end


  1. ウイルス対策で PC を高速化する方法

    多くのユーザーは、アンチウイルスが PC の速度を低下させる可能性があると誤解しています。はい、ウイルス対策によって PC の速度が低下するケースはほとんどありません。これについては、このブログで後ほど説明します。アンチウイルスが PC の速度を低下させたとしても (少し)、PC を包括的にスキャンして脅威を検出し、脅威を未然に防ぐことができます。しかし、全体として、ウイルス対策は PC のパフォーマンスを向上させるのに役立ちます。 優れた有料および無料のウイルス対策がいくつかあります そこに。このブログでは、入手可能な最高のアンチウイルスの 1 つである Systweak Antiviru

  2. 休止状態のアプリが Android のパフォーマンスを向上させる方法

    時間の経過とともに、バックグラウンドで実行されているアプリが原因で、ほとんどの Android デバイスの速度が低下します。悲しいことに、この技術的に高度な時代では、物事はこのように機能するべきではありません。 Android アプリは、自分自身を閉じてメモリを解放できるほどスマートである必要があります。 しかし、私たちは皆、物事がこのように機能しないことを知っています.したがって、RAM を解放してバッテリー寿命を延ばすには、アプリを休止状態にし、RAM を増やし、ジャンク ファイルをクリーンアップし、さらに多くのことを行うためのソリューションを見つける必要があります。簡単に言えば、パフ