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

使用Prawn pdf gem打印超过5000页的pdf需要很长时间,pdf,pdf-generation,prawn,Pdf,Pdf Generation,Prawn,我使用虾pdf宝石打印pdf 我正在将数据格式化为表格,然后将其打印到pdf。我有大约5000页(约50000条)要打印,这需要永远的时间。对于少量页面,它的快速。。。有什么办法可以提高打印速度吗 此外,不使用表格格式的数据进行打印也很快。请帮我解决这个问题 代码: format.pdf { pdf = Prawn::Document.new(:margin => [20,20,20,20]) pdf.font "Helvetica" pdf.font_size

我使用虾pdf宝石打印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
format.pdf{
pdf=Prawn::Document.new(:margin=>[20,20,20,20])
pdf.font“Helvetica”
pdf.font\u大小12
@test\u points\u all=Hash.new
dataset_id=dataset.where(collection_success:true)。顺序('created_at DESC')。首先
如果(inode.leaf?)
meta=MetricInstance.where(数据集\u id:数据集\u id,文件\u或文件夹\u id:inode.id)。包括(:测试点,:文件\u或文件夹,:数据集)。首先
@test\u points\u all[inode.name]=meta.test\u points
其他的
节点2=[]
nodes2=inode.leaves
如果(!nodes2.nil?)
节点2.每个do |节点|
meta=MetricInstance.where(数据集\u id:数据集\u id,文件\u或文件夹\u id:节点.id)。包括(:测试点,:文件\u或文件夹,:数据集)。首先
@测试点A=元测试点
如果(!@test_pointa.nil?)
@test\u points\u all[node.name]=@test\u pointa
结束
结束
结束
结束
@测试所有点。每个点都有关键点|
表#u data=[[“#{key}”,“433”,“xyz”,“xyz”]]
每个do |测试点|
td=TestDescription.find(:first,:conditions=>[“test\u point\u id=?”,test.id])
如果(!td.nil?)
表\u数据500,:单元格\u样式=>{:内联\u格式=>true,:边框\u宽度=>0},:行\u颜色=>[“FFFFFF”,“DDDDDD”])
pdf.text“”
pdf.do
pdf.水平线(0570)
结束
pdf.下移(5)
结束
结束
pdf.页数(共页){
:开始计数=>1,
:page|u filter=>lambda{| pg | pg>0},
:at=>[pdf.bounds.right-50,0],
:align=>:右,
:大小=>9
})
pdf.render_file.join(Rails.root,“app/reports”,“x.pdf”)
filename=File.join(Rails.root,“app/reports”,“x.pdf”)
发送文件名,:filename=>“x.pdf”,:type=>“application/pdf”,:disposition=>“inline”
结束

这两行中的第一行是没有意义的,拿出来

nodes2 = []
nodes2 = inode.leaves
根据您的信息,我了解到以下对数据库的查询似乎执行了50000次左右……根据表的容量和内容,执行一次查询(获取整个表)可能非常合理在整个脚本开始时,将这些数据保存在内存中,以便在纯Ruby中对其执行任何后续操作,而无需与数据库通信。然后,如果您正在使用的表非常大,它也可能会完全阻塞您的内存,这根本不是一个好主意。这真的取决于…所以请解决它

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

另外,如果如你所说,不带表格的打印速度非常快,你可以通过重新实现你自己实际使用的表格功能的一小部分来实现一个主要的加速,只使用prawn的低级功能。为什么?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.find(:first,:conditions=>[“test\u point\u id=?”,test.id])
如果(!td.nil?)

table_data我的应用程序正在处理大量数据并查看应用程序的性能…我不认为将所有条目保存在内存中是一个可行的选择…但是正如您所说,运行数据库查询50k次并不好…您是否看到其他替代方法…例如逐块获取记录或类似的方法?如果是您可以找到一种合理的方法,将数据库中的数据分组并分割成更大的块,这也是一种选择!我想强调的是,我的最后一个建议可能对您来说最重要(正如您所说的,是表格导致了实际的速度下降,而不是您以前的代码)。因此,如果您仍然需要,请集中精力做好这一点,然后利用其他选项。:)
td = TestDescription.where(test_point_id: test.id)
  .pluck(:name, :header_info, :comment_info, :line_number).first
table_data << td unless td.blank?