使用Prawn pdf gem打印超过5000页的pdf需要很长时间

时间:2013-07-23 14:00:44

标签: pdf pdf-generation prawn

我正在使用prawn pdf gem来打印pdf。

我将数据格式化为表格,然后将其打印到pdf。我有大约5000页(大约50000个条目)打印,它需要永远。对于少量页面,它很快......有什么办法可以提高打印速度。

此外,没有表格格式的数据打印很快。请帮帮我。

代码:

format.pdf {

    pdf = Prawn::Document.new(:margin => [20,20,20,20])
    pdf.font "Helvetica"
    pdf.font_size 12

    @test_points_all = Hash.new
    dataset_id = Dataset.where(collection_success: true).order('created_at DESC').first

    if(inode.leaf?)
        meta=MetricInstance.where(dataset_id: dataset_id, file_or_folder_id: inode.id).includes(:test_points,:file_or_folder,:dataset).first
        @test_points_all[inode.name] =  meta.test_points                 
    else
        nodes2 = []
        nodes2 = inode.leaves

        if(!nodes2.nil?)
            nodes2.each do |node|
                meta=MetricInstance.where(dataset_id: dataset_id, file_or_folder_id: node.id).includes(:test_points,:file_or_folder,:dataset).first
                @test_pointa = meta.test_points
                if(!@test_pointa.nil?)
                    @test_points_all[node.name] = @test_pointa
                end
            end    
        end
    end

    @test_points_all.each do |key, points|
        table_data = [["<b> #{key} </b>", "<b>433<b>","xyz","xyzs"]]
        points.each do |test|
            td=TestDescription.find(:first, :conditions=>["test_point_id=?", test.id])

            if (!td.nil?)
               table_data << ["#{test.name}","#{td.header_info}","#{td.comment_info}","#{td.line_number}"]
            end

            pdf.move_down(5)
            pdf.table(table_data, :width => 500, :cell_style => { :inline_format => true ,:border_width => 0}, :row_colors => ["FFFFFF", "DDDDDD"]) 

            pdf.text ""

            pdf.stroke do
                pdf.horizontal_line(0, 570)
            end

            pdf.move_down(5)
        end
    end


    pdf.number_pages("<page> of <total>", {
                    :start_count_at => 1,
                    :page_filter => lambda{ |pg| pg > 0 },
                    :at => [pdf.bounds.right - 50, 0],
                    :align => :right,
                    :size => 9
                  })

    pdf.render_file File.join(Rails.root, "app/reports", "x.pdf")
    filename = File.join(Rails.root, "app/reports", "x.pdf")
    send_file filename, :filename => "x.pdf", :type => "application/pdf",:disposition => "inline"
end

2 个答案:

答案 0 :(得分:2)

这两行中的第一行是没有意义的,把它取出来!

nodes2 = []
nodes2 = inode.leaves

根据您的信息,我了解以下对数据库的查询似乎执行了大约50000次...根据表的数量和内容,执行一个查询可能是非常合理的(获取在整个脚本的开头,并将这些数据保存在内存中,以便在纯Ruby中对它执行任何后续操作,而无需与数据库通信。再说一次,如果你正在使用的桌子非常庞大,它可能也会完全堵塞你的记忆,根本不是一个好主意。这真的取决于...所以想出来!

TestDescription.find(:first, :conditions=>["test_point_id=?", test.id])

此外,正如您所说,如果没有表格的打印非常快,您可以通过重新实现您自己实际使用的表格功能的一小部分来实现主要加速,只有来自对虾的低级别功能。为什么? Prawn的表函数肯定是为了满足尽可能多的用例,因此包含了很多开销(至少形成了只需要准系统功能的人的视角 - 对于其他人来说,这个“开销”就是黄金!)。因此,您可以自己实现自己需要的那小部分表,这可能会给您带来重大的性能提升。试一试!

答案 1 :(得分:0)

如果您使用的是最近版本的ActiveRecord,我建议您在内循环中使用pluck。而不是:

td=TestDescription.find(:first, :conditions=>["test_point_id=?", test.id])
if (!td.nil?)
    table_data << ["#{test.name}","#{td.header_info}","#{td.comment_info}","#{td.line_number}"]
 end

请改为尝试:

td = TestDescription.where(test_point_id: test.id)
  .pluck(:name, :header_info, :comment_info, :line_number).first
table_data << td unless td.blank?

不是为每个TestDescription实例化一个ActiveRecord对象,而是只返回一个字段值数组,你应该能够直接追加到table_data,这就是你真正需要的。这意味着减少了内存使用量,减少了在GC上花费的时间。

尝试使用pluck一次检索所有条目也是值得的,在这种情况下,你有一个数组要循环。这比一次获取一个内存需要更多的内存,但比AR对象数组少得多,并且您可以保存单独的数据库查询。