8

ユーザーのアバターを保存するために、 CarrierWave (0.9.0)、Fog ( 1.14.0 )、および S3 を使用しています。特定のユーザーのアバター URL を決定するのに時間がかかっているようです。2 回目以降の通話時間は大幅に短縮されます。

config/initializers/fog.rb

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
  }
  config.fog_directory = ENV['AWS_S3_BUCKET_AVATAR']
  config.fog_public = false
end

user.rb

mount_uploader :avatar, ImageUploader

コンソール

irb(main):002:0> Benchmark.measure { user.avatar_url }
=>   0.500000   0.020000   0.520000 (  0.537884)

irb(main):003:0> Benchmark.measure { user.avatar_url }
=>   0.000000   0.000000   0.000000 (  0.001830)

irb(main):004:0> Benchmark.measure { user.avatar_url }
=>   0.000000   0.000000   0.000000 (  0.001454)

irb(main):005:0> Benchmark.measure { user.avatar_url }
=>   0.000000   0.000000   0.000000 (  0.000998)

New Relic のレポートには、user.avatar_url最大 1 秒かかる場合があります。これが非常に遅い原因は何ですか? 公開ファイルの遅い URL 生成に関する議論がありますが、私のアバターは公開されていません。


更新 1:

最初の呼び出しの前に Fog と CarrierWave を明示的に要求しても、false返されるように違いはなく、それらが既に読み込まれていることを示します。

irb(main):002:0> require 'carrierwave'
=> false
irb(main):003:0> require 'fog'
=> false
irb(main):004:0> Benchmark.measure { user.avatar_url }
=>   0.510000   0.030000   0.540000 (  1.627774)

更新 2:

アップローダは次のとおりです。

# encoding: utf-8

class ImageUploader < CarrierWave::Uploader::Base

  include CarrierWave::RMagick

  storage :fog

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :s_32 do
   process resize_to_fill: [32, 32]
  end

  version :s_40 do
   process resize_to_fill: [40, 40]
  end

  version :s_50 do
   process resize_to_fill: [50, 50]
  end

  version :s_115_120 do
   process resize_to_fill: [115, 120]
  end

  version :s_128 do
   process resize_to_fill: [128, 128]
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

end

更新 3:

user.avatar.url違いはないようです:

irb(main):003:0> Benchmark.measure { user.avatar.url }
=>   0.500000   0.030000   0.530000 (  0.926975)
4

2 に答える 2

4

フォグのrequireはまだ問題になっていると思います(今はあまり明白ではありませんが)。フォグには非常に多くの異なるものが含まれているため、必要になるまで多くの依存関係のロードを延期するという選択をかなり前に行いました。これには「霧」の速度が上がるという利点がありますが、特定のことが最初に発生したときに速度が低下するという不利益が生じる可能性があります。この部分をどのように忘れたのかはわかりませんが、マシンで小さなベンチマークを実行すると、これを考慮すると確かに速度が低下することがわかります.

これを回避するには、上記の関連する必要なベンチマークを次のように変更できます。

require 'benchmark'
require 'fog'
Fog::Storage.new(
  provider: 'AWS',
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
  aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
)
Benchmark.measure { ... }

その接続を使用しないという点で少し奇妙に思えるかもしれませんが、それを行うまで S3 仕様のロードを延期するように設定しました (たとえば、使用するために S3 仕様をロードする必要がないようにします)。 EC2)。ただし、少し前に接続を初期化することで、そのオーバーヘッドを回避できます。うまくいけば、少なくともあなたがなりたい場所に近づくことができます.

于 2013-07-31T15:06:00.393 に答える
2

私はこれに時間を費やしました。根本的な原因を突き止めていませんが、いくつかの発見があります。私が行ったことから始めることができます。うまくいけば、これについてあまり心配する必要はありません。

  • あなたが言ったことと私の実験に基づいています。この遅さは、最初にuser.avatar_urlを呼び出したときにのみ発生します。最初の呼び出しの後にuser.avatar_urlまたはanother_user.avatar_urlを呼び出すと高速です。基本的にこの「問題」の影響を受けるリクエストは 1 つだけなので、大きな問題ではないと思います。
  • 最初の呼び出しとその後の呼び出しの違いは何ですか? ruby-profを使用して違いを確認することをお勧めします。私は専門家ではありませんが、レポートから、最初の実行は 2 回目の実行よりも多くのものをロードすることがわかります。ruby-prof は、あなたに役立つかもしれない他のレポート、特にツリーレポートを提供します。

  • URL が存在することを確認するために、CarrierWave/Fog が S3 にアクセスする必要があるのではないかと考えました。これは、不適切な S3 バケットを使用することで除外されました。

上記のレポートは、以下のコードによって生成されます。

user = User.first
RubyProf.start
user.avatar_url
results = RubyProf.stop

File.open "/tmp/profile-graph1.txt", 'w' do |file|
  RubyProf::FlatPrinter.new(results).print(file)
end

RubyProf.start
user.avatar_url
results = RubyProf.stop

File.open "/tmp/profile-graph2.txt", 'w' do |file|
  RubyProf::FlatPrinter.new(results).print(file)
end
于 2013-08-10T08:05:47.883 に答える