Основные проблемы использования памяти с Prawn на JRuby

У нас были серьезные проблемы с использованием памяти при компиляции больших документов (несколько сотен страниц +) с использованием Prawn с JRuby on Rails и Torquebox.

Наше приложение в основном позволяет пользователям загружать кучу документов PDF и объединяет их в один. Часть Prawn берет список файлов, перебирает каждый из них постранично, вставляет каждую страницу в наш выходной документ через document.start_new_page(template: 'filename') и делает некоторые незначительные добавления (рисование номеров страниц и вкладок) к каждой странице после ее вставки. Часть соответствующего кода скопирована ниже.

Хотя некоторые из файлов, которые мы генерируем, довольно велики, использование памяти все еще кажется чрезмерным. Например, для создания файла размером 38 МБ потребовалось более 4 ГБ ОЗУ (!). Этот конкретный файл был создан путем сопоставления 30 файлов, самые большие из которых имеют размер 7 МБ и 5 МБ, а большинство - всего несколько 100 КБ - но нам пришлось увеличить размер кучи Java до 5 ГБ, чтобы предотвратить падение сервера.

Должны ли мы удивляться, что наш объем использования памяти так высок? Мы делаем что-то не так, и есть ли решение? Большое спасибо.

Настройка нашего сервера:

Версия JRuby: 1.7.4 Версия Rails: 4.0.0, работает в рабочем режиме Torquebox: 3.0.0 ОС: Ubuntu 12.04 Версия LTS Prawn: 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

Вот самая важная часть кода: 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 ответов

Другие вопросы по тегам