与JRuby上的Prawn有关的主要内存使用问题

时间:2013-09-17 10:41:10

标签: memory jruby prawn jrubyonrails torquebox

使用Prawn和JRuby on Rails和Torquebox编译大型文档(数百页+)时,我们遇到了严重的内存使用问题。

我们的应用程序基本上允许用户上传一堆PDF文档并将其整理为一个。 Prawn部分获取一个文件列表,逐页遍历每个文件,通过document.start_new_page(template: 'filename')将每个页面插入到我们的输出文档中,并在插入后对每个页面进行一些小的添加(绘制页码和标签)它。下面复制了一些相关代码。

虽然我们生成的一些文件相当大,但内存使用量似乎仍然不成比例。例如,生成一个38MB的文件占用了超过4GB的RAM(!)。这个特殊文件是通过整理30个文件创建的,其中最大的两个是7MB和5MB大小,大多数只有几个100KB - 但我们不得不将Java的堆大小增加到5GB以防止服务器崩溃。

我们的内存使用量如此之高,我们应该感到惊讶吗?我们做错了什么,有没有修复?非常感谢。

我们的服务器设置:

JRuby版本:1.7.4 Rails版本:4.0.0,在生产模式下运行 Torquebox:3.0.0 操作系统:Ubuntu 12.04 LTS 虾版:1.0.0rc2 JAVA_OPTS:-server -XX:+ UseCompressedOops -Xms512m -Xmx5000m -XX:MaxPermSize = 512m -Djava.net.preferIPv4Stack = true -Djboss.modules.system.pkgs = org.jboss.byteman -Djava.awt.headless = true < / p>

这是代码中最相关的部分:为每个输入文件调用一次add_file()。请注意,调用@document.start_new_page(),实际上会插入一个新页面,然后调用start_new_page(),但不会插入新页面但确保page.dictionary.date已正确设置。我不知道这是否与我们的记忆问题有关。

  def create_or_update_document(opts)
    if @document
      @document.start_new_page(opts)
    else
      opts[:margin] = 0
      @document = Prawn::Document.new(opts)   
      @document.font_size 12
    end
  end

  def add_file(file)
    puts "     add_file() filename=#{file['full_path']}"

    filename = file['full_path']
    num_pages = file['pagecount']

    (1..num_pages).each do |page_number|
      puts "     Adding page: #{page_number}"

      # take the page defined in file 'filename' and insert it into the 
      # @document we're building
      create_or_update_document(:template => filename, :template_page => page_number)

      # this call to start_new_page doesn't change our @document, but
      # it ensures that 'page.dictionary.data' contains the settings
      # (:Rotate, etc) from the source PDF
      start_new_page(:template => filename, :template_page => page_number)

      puts "      Page size: width=#{page_width} height=#{page_height} Rotate: #{page.dictionary.data[:Rotate]}"


      # add destination for internal links e.g. from table of contents or tabs
      @document.add_dest("page#{@current_page_number}", @document.dest_fit)

      rotation = page.dictionary.data[:Rotate]
      case rotation
      when 90
        translate_x = 0
        translate_y = -page_width
        page_number_x = page_height - RightMargin
        tab_page_height = page_width

      when 180
        translate_x = -page_width
        translate_y = -page_height
        page_number_x = page_width - RightMargin
        tab_page_height = page_height

      when 270
        translate_x = -page_height
        translate_y = 0
        page_number_x = page_height - RightMargin
        tab_page_height = page_width

      else
        translate_x = 0
        translate_y = 0
        rotation = 0
        page_number_x = page_width - RightMargin
        tab_page_height = page_height
      end

      @document.rotate(rotation, :origin => [0,0]) do
        @document.translate(translate_x,translate_y) do
          if @pack.include_tabs
            add_tabs(tab_page_height, page_number_x, @current_page_number)
          end
          @document.text_box "<font name='Georgia' size='12'>#{@current_page_number}</font>", at: [page_number_x, BottomMargin + 14], inline_format: true, width: RightMargin + 100
        end
      end

      @current_page_number = @current_page_number + 1
    end
  end

0 个答案:

没有答案