Pdf/writer: table.render_on best practices?


#1

Hi All,

I generate a pdf report that contains a table. The report is 14 pages,
and
it takes 20s to be rendered. Most of these 20s are spend in the
render_on
method. I wonder if it is possible to speed up that process?

To create the report, I do the following:

  1. Setup pdf layout:

Setup pdf layout

  pdf.select_font("Helvetica", { :encoding => "WinAnsiEncoding"})
  pdf.text " ", :font_size => 12, :justification => :center
  s = 9
  t = 'Seite <PAGENUM>'
  y = pdf.absolute_bottom_margin - 5
  x = pdf.absolute_right_margin
  x -=(pdf.text_width('Seite XX', s))
  pdf.start_page_numbering(x, y, s, nil, t, nil)
  pdf.open_object do |heading|
     pdf.save_state
     pdf.stroke_color! Color::Black
     pdf.stroke_style! PDF::Writer::StrokeStyle::DEFAULT
     s = 9
     t = "My title - " + Date.today().to_s
     w = pdf.text_width(t, s) / 2.0
     x = pdf.margin_x_middle
     y = pdf.absolute_top_margin
     pdf.add_text(x - w, y, t, s)
     x = pdf.absolute_left_margin
     w = pdf.absolute_right_margin
     y -= (pdf.font_height(s) * 1.01)
     pdf.line(x, y, w, y).stroke
     y = pdf.absolute_bottom_margin + pdf.font_height(9) - 2
     pdf.line(x, y, w, y).stroke
     pdf.restore_state
     pdf.close_object
     pdf.add_object(heading, :all_pages)
  end
  1. create a table:
    table = PDF::SimpleTable.new

  2. populate the table
    table.data = dataArray

  3. set which rows are displayed, and in which order:
    table.column_order = rows
    (Note: only some rows are displayed)

  4. I set the width:
    table.width = pdf.absolute_right_margin - pdf.absolute_left_margin

  5. I call table.render_on(pdf):
    table.render_on(pdf)

  6. I send the file with send_file

Steps 1,2,3,4,5 and 7 takes less than 2 sec altogether. Step 6 takes
about
17s. I must say that the margins are not correct, and that the table
goes
over the header and footer of my document (does it matter for rendering
time?)

Any clue of what I could do to speed this up? or maybe this is normal
speed?

Regards,

Nicolas


#2

On 5/5/06, Nicolas B. removed_email_address@domain.invalid wrote:

I generate a pdf report that contains a table. The report is 14 pages, and
it takes 20s to be rendered. Most of these 20s are spend in the render_on
method. I wonder if it is possible to speed up that process?

SimpleTable#render_on is slow. There may be ways to speed it up, but I
have not had time to investigate them yet.

-austin


#3

OK, then I’ll just live with it - and maybe show a blinking “please
wait” to
the user. There is no way to avoid a “render_on”, right?

Thanks,

Nicolas


#4

On 5/5/06, Nicolas B. removed_email_address@domain.invalid wrote:

OK, then I’ll just live with it - and maybe show a blinking “please wait” to
the user. There is no way to avoid a “render_on”, right?

Not if you want that table. :wink:

-austin


#5

On 5/5/06, Jodi S. removed_email_address@domain.invalid wrote:

Hey Austin,

I’m also generating a big table - probably 100 pages or more
(inventory report) - the client currently sets it up to print overnight.

While this is ‘ok’, I’d prefer to speed it up for them. I’d be
willing to take a look at the table rendering code - Do you have any
hints on where I’d focus my attention?

Transaction::Simple. Or at least the use thereof.

Transaction::Simple does its job well, but I’m not currently doing a
good job of clearing unused data and keeping too much rewind
information, I think. Reducing that should bring a performance boost.
Figuring out a way to precalculate the size of the data so that rewind
doesn’t have to happen would be good, too. It would be cheaper to
simulate to set up pagination points than to recover if we do need to
paginate.

-austin


#6

On 5-May-06, at 1:03 PM, Austin Z. wrote:

-austin

Ok. after much rumination and consideration about writing a
preprocessor it became clearer that the transactions were the
(slowdown) culprit(duh), and if I’m dealing with a huge number of
rows then split_rows should NEVER be set to true, as the (rewind)
rollback condition would never occur, and thus the transaction space
would fill up - 1 transaction per row.

…and \me had split_rows set to false (default value).

grin.

after using the correct setting I’m looking at a 1000% speedup.

So the only code improvement I might suggest Austin would be to set
split_rows to true if render_on detects more rows than can ever be
fit on one page - or perhaps a private that does the same thing
without changing the programmers interface.

Nicolas you might check to see if you’ve set split_rows correctly -
you’ll get the same pdf output, but transactions won’t be used to
hold row state.

cheers,
Jodi


#7

Thanks Jodi, great advice!


#8

Hey Austin,

I’m also generating a big table - probably 100 pages or more
(inventory report) - the client currently sets it up to print overnight.

While this is ‘ok’, I’d prefer to speed it up for them. I’d be
willing to take a look at the table rendering code - Do you have any
hints on where I’d focus my attention?

cheers,
Jodi