RMagick - 在不泄漏内存的情况下创建缩略图的正确方法

时间:2012-11-15 21:15:47

标签: ruby-on-rails-3 passenger rmagick

我正在使用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这表明我会遇到一个基本问题喜欢解决。

奇怪或不是,如果我用另一张大小相同的图像重新运行测试,内存使用量不会再次大幅跳跃(幸运的是)。

任何合理的想法都会受到赞赏,特别是考虑到我可以节省多少内存。

1 个答案:

答案 0 :(得分:0)

尝试使用minimagic,这是为了解决你遇到的问题。

对于大多数任务,the minimagic gem linked here就足够了。它运行ImageMagick的命令行工具,这意味着创建一个新进程,它运行,然后停止,释放内存。我们用MiniMagic取代了RMagic,我们的记忆困境已成为过去。