<div dir="ltr"><div><div>Hey guys,<br><br></div>last time I wrote about some problems how bcrypt (at least current erlang bcrypt implementations) cannot be scale. The original problem what that bcrypt driver (github chef/erlang-bcrypt) is using port and nif implementation. The nif implementation behind the scenes it uses a gen_server which serializes all the requests are coming. The port implementation uses a port pool which can be configured.<br><br></div><div>Our problem comes from the fact that a good hashing algorithm should be slow by design. bcrypt uses a round parameter (3-16) with which one can say that bcrypt should use 2^(3-16) cycles during computing. According to security guidelines a good hashing algorithm should take 0.1-0.5 seconds to be computed, so now bcrypt should run with round 10-12 depending on the hardware. It needs to be slow in order that one cannot find a hash-collision easily.<br><br></div><div>Now you can imagine the problem. With load tests we easily made message queues and the problem is that the computing has sometimes very very big latencies (50-60 seconds depending on the number of concurrent users). The nif implementation spoils one scheduler thread but if I have 32 cores I cannot scale the computing.<br><br>The problem I wanted to solve is to split the bcrypt_hashpw nif into 3 parts: initialization, computing some predefined number of rounds, encryption. I used enif_schedule_nif to schedule the computing of the next task.<br><br></div><div><a href="https://github.com/jonasrichard/erlang-bcrypt/blob/master/c_src/bcrypt_nif.c">https://github.com/jonasrichard/erlang-bcrypt/blob/master/c_src/bcrypt_nif.c</a><br><br></div><div>The implementation is based on chef/erlang-bcrypt and vinoski/bitwise. The first loadtests are promising since latencies are much more even. With 10 concurrent users (basho bench + bcrypt driver) the latency was (500ms 1100ms / mean median), with 50 users (2800ms ~6000ms) which 5x increase, let us say.<br><br></div><div>My questions are:<br></div><div>- how can I measure if my nif "slices" took no longer than 1ms<br></div><div>- how can I implement some kind of adaptive computing? My bcrypt_compute computes 64 rounds which sometimes below 1ms, sometimes above 1ms.<br><br><a href="https://github.com/jonasrichard/erlang-bcrypt/blob/bb96149332c8c6b6135698dfbc21e19e554bc066/c_src/bcrypt_nif.c#L133">https://github.com/jonasrichard/erlang-bcrypt/blob/bb96149332c8c6b6135698dfbc21e19e554bc066/c_src/bcrypt_nif.c#L133</a><br><br></div><div>If I use some kernel gettime function, can it cause blocking?<br><br></div><div>- how can I be sure that no garbage left in memory. I try to watch out putting release functions in correct places but it would be good to measure.<br></div><div><br></div><div>Thanks,<br></div><div>Richard<br></div><div><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div>Richard Jonas</div><div>Erlang Solutions Hungary Kft</div><div><br></div><div>Address:</div><div>  Riverpark Office K.32</div><div>  Közraktár street 32. 3/1.</div><div>  1093 Budapest</div><div>  Hungary</div><div>Phone/fax:</div><div>  +36-1-7000-654</div></div></div>
</div></div>