A quick benchmark on the resources required to generate a QR code

So as part of the qrplop project, I’m trying to figure out just how processor intensive will it be to generate lots and lots of qr codes. Mind you, no one will probably ever use the silly thing, but I don’t want to have to pay some hosting provider a lot of money to host it no matter if 1 person is using it or 1000. This is a side project for fun, and efficiency matters to me.

So, the perl module I am using right now is Imager::QRCode. It’s a perfectly OK module, not great. It builds off of the Imager series of modules, and for the life of me I can’t figure out how to write the value to a scalar instead of a file, but that’s for another time. So, my code is really quite dead simple:

I really had three major questions:

  1. How many could I crank out of a single thread from a single machine?
  2. Did the file format I wrote them out to make a considerable difference in performance?
  3. Did it make sense to cache the factory object (was that a considerable overhead.)

So, for point #1, the answer is pretty awesome. On a single machine, in a single thread, I can easily generate, from scratch, about 25 qr codes per second. So, that’s sitting at right around 1500 qr codes a minute. Quite frankly, if I ever get to the point where qrplop has to generate more than 1500 qr codes per minute, I’m hoping I can afford more than a single thread on a single machine.

bash-3.2$ dumbbench — scripts/qrperf.pl 25 1 gif
cmd: Ran 22 iterations (2 outliers).
cmd: Rounded run time per iteration: 1.64e-01 +/- 1.2e-02 (7.3%)

For point #2, does the file format make a difference? Well, fundamentally it feels like it should. A format like jpeg requires compression, a format like gif less, a format like pnm sure as shit shouldn’t. So, we run some benchmarks:

bash-3.2$ for object in “gif” “png” “jpg”
> do
> echo “Testing $object”
> dumbbench — scripts/qrperf.pl 100 1 $object
> done
Testing gif
cmd: Ran 37 iterations (1 outliers).
cmd: Rounded run time per iteration: 5.43e-01 +/- 5.3e-02 (9.8%)
Testing png
cmd: Ran 63 iterations (1 outliers).
cmd: Rounded run time per iteration: 1.32e+00 +/- 1.3e-01 (9.8%)
Testing jpg
cmd: Ran 28 iterations (0 outliers).
cmd: Rounded run time per iteration: 4.36e-01 +/- 4.2e-02 (9.7%)

Holy moly, is that possible? Does PNG generation really take an order of magnitude *more* time than jpeg or gif? The only difference is that giflib and libjpeg were installed by homebrew, and libpng is the one that comes standard on OSX in /usr/X11/lib.  That’s definitely going to require some more looking in to! But for now, for my tests, I will (sadly) not be generating PNGs.

So how about point #3. How much, of the total time, is eaten up by instantiating the actual Imager::QRCode object? What if I can safely store that away in some application level variable in my Dancer/Plack app, and don’t have to bother reinstantiating it.  Well benchmarking once again:

bash-3.2$ for object in “gif” “png” “jpeg”; do for cached in “0” “1”; do echo “Testing $object cached is $cached”; dumbbench — scripts/qrperf.pl 100 $cached $object; done; done
Testing gif cached is 0
cmd: Ran 21 iterations (0 outliers).
cmd: Rounded run time per iteration: 5.981e-01 +/- 1.0e-02 (1.7%)
Testing gif cached is 1
cmd: Ran 21 iterations (1 outliers).
cmd: Rounded run time per iteration: 4.54e-01 +/- 3.7e-02 (8.2%)
Testing png cached is 0
cmd: Ran 20 iterations (0 outliers).
cmd: Rounded run time per iteration: 1.374e+00 +/- 2.9e-02 (2.1%)
Testing png cached is 1
cmd: Ran 21 iterations (1 outliers).
cmd: Rounded run time per iteration: 1.09e+00 +/- 1.1e-01 (9.9%)
Testing jpeg cached is 0
cmd: Ran 20 iterations (0 outliers).
cmd: Rounded run time per iteration: 5.184e-01 +/- 8.5e-03 (1.6%)
Testing jpeg cached is 1
cmd: Ran 25 iterations (0 outliers).
cmd: Rounded run time per iteration: 4.12e-01 +/- 4.1e-02 (9.9%)

Seems pretty straightforward to me. On average I saved about 20-25% of the generation time by being smart and not instantiating the factory object more than absolutely necessary.  Seems real straightforward, but 20% if a pretty big savings to just get by being smart about not re-instantiating an object.  In this day and age of PaaS, where we’re not far away from paying by the watt, this is an optimization to keep in your pocket.

TL/DR – Generating QR codes is fast. File format really matters, maybe based on what library you link to. Cache your factory if you can, it’s a cheap 20% savings.

Advertisements
This entry was posted in tech and tagged , , , , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

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