私はRMagickを使用して、Rails 3アプリ(Passengerで実行)でかなり単純な画像操作を行っています。破棄を使用しているにもかかわらず、関連するメモリリークを制御しようとしてひどい経験をしています!方法。注意すべき重要な点は、受信画像が透明なPNGである可能性があることです。私は、RMagickが使用するデフォルトの黒ではなく、白の背景に画像を配置したいと考えています。他はPDFかもしれません、その場合私は最初のページを使いたいです。
現在、3.6MBのJPEGのサイズを変更すると、110MBのメモリリークが発生します。
だから、誰かが私のサンプルを見て、おそらく私が間違っているところを見つけることができますか?
path = 'some/path'
page_id = "0"
in_doc_o = nil
begin
in_doc_o = ImageList.new(path+"[#{page_id}]")
# Create a white background layer
in_doc_temp = in_doc_o.new_image(in_doc_o.first.columns, in_doc_o.first.rows) { self.background_color = "white" }
in_doc = in_doc_o.reverse.flatten_images
in_doc.format = "jpg"
rescue
# Something went wrong so create a dummy 'error' image
in_doc = ImageList.new("public/images/doc.jpg"+"[#{page_id}]")
end
in_doc.change_geometry!('600x200>') { |cols, rows, img| img.resize!(cols, rows) }
out_blob = in_doc.to_blob() { self.quality = 60 }
res = save_to_special_storage_device(out_blob)
mime_type = in_doc.mime_type
begin
in_doc.each {|img| img.destroy!}
rescue=>e
Rails.logger.info "rescued attempting destroy on in_doc image list #{e.inspect}"
end
begin
in_doc_o.each {|img| img.destroy!}
rescue=>e
Rails.logger.info "rescued attempting destroy on in_doc_o image list #{e.inspect}"
end
begin
in_doc.destroy!
in_doc_o.destroy! unless in_doc_o.nil?
in_doc = nil
in_doc_o = nil
in_doc_temp.destroy! if in_doc_temp
in_doc_temp = nil
rescue
Rails.logger.info "rescued attempting image cleanups"
end
GC.start
PNGを事前に識別し、空白の白い画像を作成しないことで、もう少しコードを犠牲にしていくつかの問題を節約できると思いますが、テストではまだ60MBをリークしています。これは、解決したい根本的な問題を示唆しています。 。
不思議なことに、またはそうではないが、ほぼ同じサイズの別の画像を使用してテストを再実行した場合、メモリ使用量が2回目に大幅に増加することはありません(幸いなことに)。
特に私がどれだけのメモリを節約できるかという観点から、合理的なアイデアをいただければ幸いです。