学習日記

学習記録

プログラムのパフォーマンスを考える

前書き

Rubyに置けるコードの効率性を考えてみました

現段階では小規模なコードを書いているので問題になりませんが、将来的に大規模なコードを書くときに思わぬところでボトルネックを生み出さないように訓練する一環です。

またこの記事はフィヨルドブートキャンプ内でdocsとして共有されていた題材を元にしています。

パフォーマンスの悪いコード

以下のようなプログラムを書きました

  • 1から30までの整数を30個ランダムに生成し、配列として保持します
  • 配列を順に出力していき、配列内の最小値、最大値の場合にそれを明示します
#!/usr/bin/env ruby

def main
  numbers = Array.new(30) {rand (1..30) }
  numbers.each do |n|
    puts "#{n}#{":最小値です" if min_calc(numbers) == n }#{":最大値です" if max_calc(numbers) == n }"
  end
end

def min_calc(numbers)
  sleep 0.5
  numbers.min
end

def max_calc(numbers)
  sleep 0.5
  numbers.max
end

main

sleepを入れているのは実行される度に処理が走っていることを実感するためです。 つまり処理の度に何回も関数を呼び出すのは、必要がなければやめたほうがいいということです。

実際このプログラムを起動してみると、かなりじれったい動作をすることが分かります

パフォーマンスの良いコード

これを変数に格納してしまい、以下のようなコードにすれば

#!/usr/bin/env ruby

def main
  numbers = Array.new(30) {rand (1..30) }
  min_number = min_calc(numbers)
  max_number = max_calc(numbers)
  numbers.each do |n|
    puts "#{n}#{":最小値です" if min_number == n }#{":最大値です" if max_number == n }"
  end
end

def min_calc(numbers)
  sleep 0.5
  numbers.min
end

def max_calc(numbers)
  sleep 0.5
  numbers.max
end

main

前のコードに比べて随分実行速度が速くなるはずです。

このコードの場合はそもそもメソッドに分割する意味はないですが、分かりやすいようにメソッドはそのままにしてあります。

ループ内で重い処理はできるだけ行わないように気を付けたいですね!