【问题标题】:Ruby: Prawn PDF out of memory when using the group methodRuby:使用组方法时Prawn PDF内存不足
【发布时间】:2010-11-17 23:25:46
【问题描述】:

我想以 pdf 格式显示大量带有类别标题的产品。如果某个类别不适合当前页面,我想将其移至下一个。为此,我使用了 Prawn 的 group 方法。

Product.all.group_by(&:category).each do |category, products|
  pdf.group do
    # Simplified the data a bit for this example
    pdf.text category
    pdf.table products.map{ |p| [p.title, p.price] }
  end
end

这对于少量产品非常有效,但是当我添加超过 100 个左右时,它需要很长时间,然后以“分配内存失败”结束。如果我不使用 group 方法大约需要 30 秒。

显然 group 方法不能很好地管理它的内存使用。任何解决方法的建议将不胜感激。

【问题讨论】:

  • 在通过 SO 进行更多搜索后,我想我找到了一个可以满足我需求的解决方法:stackoverflow.com/questions/2081635。不幸的是,使用这种方法有完全相同的问题:一段时间后,进程开始占用 100% cpu 并最终导致“分配内存失败”
  • 我仍然想知道这个问题的答案,所以我决定添加一个赏金。嘿,值得一试。
  • 我在使用 Prawn 和 group 方法时遇到了同样的问题。看起来小组工作正常,直到 PDF 中的第 50 组。那时,遍历后续组需要很长时间。

标签: ruby pdf out-of-memory prawn


【解决方案1】:

我在一个项目上使用了 prawn,很抱歉,但这是一场灾难,最后我们不得不切换到 wicked pdf。我建议您在不需要太多代码之前也这样做。

【讨论】:

  • 感谢您的建议,我开始有同样的想法。不幸的是,我需要基于现有的仅打印设计非常精确的格式。邪恶的 pdf 我认为使用 html 转换。不过,我正在研究其他选项,例如 pdf-writer。
  • 我想不会有更好的答案。我决定切换到 pdf-writer,尽管它进展缓慢。真的很遗憾 Prawn 不能很好地处理这些东西,因为从语法上讲,它是迄今为止我遇到的最方便的 PDF 库。
【解决方案2】:

---------更新的答案--------

之前的解决方法对于生产服务器来说不够好,所以我不得不使用来自 git repo 的开发版本作为 vendor/prawn 下的子模块安装,如下所述:https://github.com/sandal/prawn/wiki/Using-Prawn-in-Rails

group 方法的内存问题已经解决,但语法/选项发生了一些变化。所以我不得不重写代码来生成PDF。

此外,让子模块与 Rails 应用程序的 git 存储库很好地配合是很困难的。部署到生产环境非常困难。

--------- 原始答案--------

这不是一个修复方法,但它会使问题在它出现之前需要更多的组迭代:

  • 覆盖名为“组”的 Prawn::Document 实例方法
  • 使用来自 prawn 的最新开发版本(来自 github.com)的 'group' 函数中的代码

我这样做的方法是将一个文件添加到我的 Rails 应用程序的 /lib 文件夹中。该文件将包含 Prawn gems 并为 PDF 文档定义 mime 类型:

class PdfPrawn
  require 'prawn'
  require 'prawn/core'
  require 'prawn/table'
  MIME_TYPE = "application/pdf"
end
class Prawn::Document
  def group(second_attempt=false)
    old_bounding_box = @bounding_box
    @bounding_box = SimpleDelegator.new(@bounding_box)

    def @bounding_box.move_past_bottom
      raise RollbackTransaction
    end

    success = transaction { yield }

    @bounding_box = old_bounding_box

    unless success
      raise Prawn::Errors::CannotGroup if second_attempt
      old_bounding_box.move_past_bottom
      group(second_attempt=true) { yield }
    end

    success
  end
end

然后在模型文件中,我定义了一种方法来生成我的 PDF 并使用如下内容:

def to_pdf
  require "#{File.expand_path(RAILS_ROOT)}/lib/pdf_prawn"
  pdf = Prawn::Document.new
  # code to add stuff to PDF
  pdf.render
end

【讨论】:

  • 抱歉,回复晚了。谢谢你提醒我,我升级到大虾0.11.1,看来你是对的,内存问题已经消失了。我选择从头开始重写以适应新语法,它现在运行良好。再次感谢!
猜你喜欢
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多