prawnpdf/prawn — pull request #378 by alexdowad (2012-08-06 13:15:51+00:00)
Title: More than 2x speedup for generation of large tables

BACKGROUND: I am adding some functionality to a legacy Rails app. The new functionality includes the use of Prawn to export various reports to PDF format. While testing the app, I discovered that Prawn is SLOOOOWWWWWW when you try to add large tables to a document... in this case, it was taking more than 80 seconds to generate a PDF with a ~12,000 cell table. That's on the client's server, which is running Rails 2 on Ruby 1.8.7. The CPU is a 2-core Xeon (haven't checked what the clock speed is).

I discovered that using Ruby 1.9.3 doubles the speed of Prawn's table generation, but I am still looking for at least another 20-40x boost. After a little investigation, the first thing I found was that Prawn::Table#make_cells takes O(n^2) time ("n" being the total number of cells). The culprits were Prawn::Table::Cells#[]= and Prawn::Table::Cells#[].

[]= wipes out the cell index, and [] recalculates it. Since each iteration of the inner loop in #make_cells uses *both* [] and []=, this means all the cells are re-indexed for *every* cell which is added. A classic "Schmiel the painter" performance bug.

This patch speeds up my table generation benchmark by 2.4x. I'm not happy yet, but it's a good start.