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



我正在使用对虾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

这两行中的第一行毫无意义,去掉它!

nodes2 = []
nodes2 = inode.leaves

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

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

此外,如果像你所说的那样,在没有表格的情况下打印非常快,那么你可能能够通过重新实现你自己实际使用的表格功能的一小部分,只使用对虾的低级功能,来实现大的加速。为什么?Prawn的表函数肯定是为了满足尽可能多的用例,因此包含了大量的开销(至少从只需要基本功能的人的角度来看——对其他人来说,这种"开销"是金子!)。因此,您可以自己实现所需的表的一小部分,这可能会大大提高性能。试试看!

如果您使用的是最新版本的ActiveRecord,我建议在内部循环中使用pull。取而代之的是:

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时间。

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

最新更新