0

ペーパークリップ アタッチメント モデルのスクリーンショットに 2 つのスタイル (smallcard と mediumcard) を追加しました。

class Screenshot < ActiveRecord::Base
    has_attached_file :image,
    :styles => { :tiny => "x75", :small => "x245", :medium => "x480", :large => "1280x900>",
                 :smallcard => "280x245#", :mediumcard => "570x480#" },
    :storage => :s3,
    :s3_credentials => "#{Rails.root}/config/amazon_s3.yml",
    :path => "/screenshots/:id_partition/:style/:filename"
end

public/system/paperclip_attachments.yml ファイルを手動で作成して、既存のスタイルの処理を減らしました。

---
:Screenshot:
  :image:
    - :tiny
    - :small
    - :medium
    - :large

それでも rake paperclip:refresh:missing_styles CLASS=Screenshot を実行すると、次のようになります。

Regenerating Screenshot -> image -> [:mediumcard, :smallcard]
rake aborted!
Cannot allocate memory - identify -format %wx%h '/tmp/79a229e96ab52dfa760132958da47bf320120806-31260-1eleoww[0]'
Tasks: TOP => paperclip:refresh:missing_styles
[clip]

ログを追跡すると、処理は 500 番台 (ID) までしか行われません。

サーバーは確かに Ubuntu を実行している Linode 512 であり、3 つの Rails アプリと 1 つの PHP アプリのページを何年にもわたって提供してきました。これまでにメモリが不足したことはありません。

rake タスク プロセスを監視すると、使用可能なすべての RAM を使い果たすまで、処理されたイメージごとに段階的に成長します。

私のLinodeが成長する時が来たのかもしれません..しかし、最初に私はいくつかの他のオプションを望んでいます.

このメモリの問題を回避し、これら 2 つのスタイルを既存の 13k 画像に追加するにはどうすればよいですか?

ご協力いただきありがとうございます!

4

2 に答える 2

2

システムにメモリを適切に解放する機会を与える必要があります。PHP バッチ タスクに ORM を使用して同様の問題に直面したときに使用した大胆なトリックは次のとおりです。一度に 1 つの項目に対してのみ最初のタスクを呼び出す別のタスクでタスクをラップします。一般に、最初のタスクをリファクタリングして、ベース イメージの引数を取得する必要があります。2 番目のタスクはすべての画像を (メモリにやさしい方法で、たとえばオブジェクト ID などで) 収集し、それらをループ処理して、それぞれを引数として最初のタスクを呼び出します。最初のタスクが完了すると、メモリが OS に返され、メモリが解放されます。一方、2 番目のタスクまたはラッパー タスクは、一度に多くのメモリを必要としません。このように、最大​​メモリ使用量は、すべてではなく、 1 つの画像を処理するために最大にする必要があります。画像。

于 2012-08-06T21:53:35.857 に答える
0

うまくいけば、これは同じ問題を抱えている他の誰かを助けることができます.

Chris が提案したように、%x() を使用して呼び出される別の rake タスク内に 1 つの rake タスクをラップしました。各反復は、前の呼び出しからメモリを完全に解放します。

namespace :screenshots do
  desc "Incrementally rebuild thumbnails. START=0 & BATCH_SIZE=10 & VERBOSE=false"
  task :reprocess_stepper => :environment do
    batch_size = (ENV['BATCH_SIZE'] || ENV['batch_size'] || 10)
    verbose    = (ENV['VERBOSE'] || ENV['verbose'] || nil)

    total = Screenshot.count
    start = 0

    while start < total
      puts "Spawning: bundle exec rake screenshots:reprocess_some START=#{start} BATCH_SIZE=#{batch_size} VERBOSE=#{verbose} RAILS_ENV=#{Rails.env}"
      puts %x{bundle exec rake screenshots:reprocess_some START=#{start} BATCH_SIZE=#{batch_size} VERBOSE=#{verbose} RAILS_ENV=#{Rails.env} }
      start = start + batch_size.to_i
    end
  end

  desc "Reprocess a batch of screenshots. START=0 & BATCH_SIZE=10 & VERBOSE=false"
  task :reprocess_some => :environment do
    start      = (ENV['START'] || ENV['start'] || 0)
    batch_size = (ENV['BATCH_SIZE'] || ENV['batch_size'] || 10)
    verbose    = (ENV['VERBOSE'] || ENV['verbose'] || nil)

    puts "start = #{start} & batch_size = #{batch_size}" if verbose
    puts "RAILS_ENV=#{Rails.env}" if verbose

    screenshots = Screenshot.order("id ASC").offset(start).limit(batch_size).all
    screenshots.each do |ss|
      puts "Re-processing paperclip image on screenshot ID: #{ss.id}" if verbose
      STDOUT.flush
      ss.image.reprocess!
    end
  end
end

次に、このタスクを次のように呼び出すことができます。

RAILS_ENV=production bundle exec rake screenshots:reprocess_stepper VERBOSE=true BATCH_SIZE=50
于 2012-09-02T18:47:20.973 に答える