vinoski/erlsha2 — pull request #9 by bosky101 (2014-05-14 06:27:07+00:00)
Title: Based on profiling with qcachegrind, added hexlify_to_bin/1 which is nea...

## tl;dr
While profiling my app with `qCacheGrind`, in my case i found 2% of the time spent in the hexlify + hmac256
This commit introduces `hexlify_to_bin/1` which brought this down to 0.26 %

## Observation
in most systems that depend on `hmac:hmac256`, `hmac:hexlify` is used to verify signatures.

eg: http://stackoverflow.com/questions/8942359/hmac-sha256-hex-digest-of-a-string-in-erlang-how

1> hmac:hexlify(hmac:hmac256(<<"7ad3773142a6692b25b8">>, <<"POST\n/apps/3/channels/test_channel/events\nauth_key=278d425bdf160c739803&auth_timestamp=1272044395&auth_version=1.0&body_md5=7b3d404f5cde4a0b9b8fb4789a0098cb&name=foo">>)).
"309FC4BE20F04E53E011B00744642D3FE66C2C7C5686F35ED6CD2AF6F202E445"

These usually occur once for every request and since we're dealing with time-critical requests, any improvement here results in faster responses and general beam performance.

## hexlify performance
Here is a call graph of % time spent of the original hexlify code
![original_hmac_hexlify](https://cloud.githubusercontent.com/assets/25080/2967215/877deab2-db29-11e3-8efc-750116fbe906.png)

## intermediate performance
Modified hex.erl from http://necrobious.blogspot.in/2008/03/binary-to-hex-string-back-to-binary-in.html to use binary instead of lists
![intermediate_hmac_hex](https://cloud.githubusercontent.com/assets/25080/2967223/aa2f5596-db29-11e3-9a5f-9f0ac1e97a28.png)

## hexlify_to_bin/1 performance
10x improvement modifying hex to use tail recursion.
![final_hmac_hexlify_to_bin](https://cloud.githubusercontent.com/assets/25080/2967229/bb229322-db29-11e3-96ff-1e1fd52ef8ef.png)

At this point with the use of binary and tail recursion - it pretty much does not resemble hex.erl So I forked `erlsha2` and submitted this pull request.

## Can hexlify_to_bin replace hexlify ?
No. here are a few subtle differences:
- returns binary as documented in the spec
- the resultant hex will be in lower case ( as opposed to hexlify that uses B to indicate upper case )

## Tested ?
It passes the unit tests. Here is also a nieve microbenchmark which shows the performance improvement.

```erlang
> Seq1 = lists:seq(1,100).

> timer:tc(fun()-> [hmac:hexlify(<<"foo">>) || _X <- Seq1 ] end).
{2496,
["666F6F","666F6F","666F6F","666F6F","666F6F","666F6F",
"666F6F","666F6F","666F6F","666F6F","666F6F","666F6F",
"666F6F","666F6F","666F6F","666F6F","666F6F","666F6F",
"666F6F","666F6F","666F6F","666F6F","666F6F","666F6F",
"666F6F","666F6F",
[...]|...]}

> timer:tc(fun()-> [hmac:hexlify_to_bin(<<"foo">>) || _X <- Seq1 ] end).
{1527,
[<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,<<"666f6f">>,
<<"666f6f">>,<<"666f"...>>,<<...>>|...]}
```

## Conclusion
If nothing, I really recommend using `kcachegrind` or `qcachegrind` ( if on a mac ) if you want to optimize your code but not sure exactly where to start off. And oh, hope you like this PR :)