During my fellowship at Stack Exchange I’ve been working on a photo mosaic application using Rails and RMagick, a wrapper on ImageMagick for Ruby. The application takes an uploaded image and a search term from the user and returns a mosaic of that image created from google image search results for the given term.
The main issue I ran into when working on this application was how slow it ran. From start to finish the process of creating the mosaic took several minutes, even for a small number of photo tiles. My mentor at Stack Exchange helped me come up with several strategies to tackle this issue and speed up the application.
The first step to improving the performance of the application was discovering exactly which processes were causing it to be slow. This would also provide a baseline performance metric to compare against once we implemented optimizations. In order to do this we added in some simple benchmarks. Before and after each process that was run, I printed out a system timestamp.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Although writing out the puts
statements was time consuming, it gave me great readable output:
1 2 3 4 5 6 7 |
|
Initially I’d thought that assembling the photos into a mosaic has been taking the longest amount of time, but from this initial output, I was able to pinpoint the source of the delay to the photo search function. From there I put further benchmarks into the search function to get more information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
By far the slowest operation was downloading the photos and reading them into memory. This was taking 59 seconds out of a total 72 seconds! Now that I had a clear idea of how long the process was taking and which part was the bottleneck, I could begin to optimize. In part two of this post, I’ll show you my next steps.