String Concatenation

A reporting application I am working on requires the results of some quite large queries to be parsed and presented to users via a web page. The query timings are an issue themselves, requiring some creative SQL, indexes, views, and some batch jobs to shape the data for the web application to efficiently utilize it (maybe another blog post?), but the surprising thing I’ve found is the efficiency issues in just building the HTML results from the query results.

With the large quantity of queries that must be run (and individual HTML tables built on the results), I really didn’t want to rewrite the physical build of each table over-and-over. After playing with a few alternatives, I settled on providing a single table-building method.

def create_html_table(elements, cell_lambdas)

elements is an array of objects, each containing the data for one row. cell_lambdas is an array of lambdas, each with the knowledge of how to populate a single cell.

The implementation is pretty straighforward (psuedo here):

<table>
for each element
<tr>
for each lambda
<td> invoke each lambda, passing the current element</td>
</tr>
</table>

If you work at a dentist office, hockey rink, or the bar in Road House you’d create your table something like:

create_html_elements Person.find(:all), [
lambda {|person| person.first_name},
lambda {|person| person.teeth_remaining} ]

Where I was getting burned initially was in the way that I was concatenating the HTML during the iteration of each element/lambda. With the dynamic logic involved, I couldn’t simply use interpretted strings alone. Initially I implemented the first thing that came to mind, good old +=

html = ‘<table>’
element.each do |element|
html += ‘<tr>’

…etc

This, of course, worked fine. It didn’t seem tremendously inefficient (timings would later reveal each row was building in about .0118 seconds) and it got the job done. When I came back through to really try to improve efficiency though, the overall process was taking much longer than I can afford. Despite the low per row timings – this is a pretty big report and it was taking 64 seconds plus to build this HTML!

A quick review of the API and I decided to give “<<” a spin for concatenation. The results were next to unbelievable. Immediately my timings came down to just over 1 second! Incredible savings.

Advertisements

Leave a comment

Filed under Ruby

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s