[erlang-questions] Scaling bcrypt

Richard Jonas richard.jonas@REDACTED
Wed Jul 6 09:45:44 CEST 2016


Hey guys,

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.

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.

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.

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.

https://github.com/jonasrichard/erlang-bcrypt/blob/master/c_src/bcrypt_nif.c

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.

My questions are:
- how can I measure if my nif "slices" took no longer than 1ms
- how can I implement some kind of adaptive computing? My bcrypt_compute
computes 64 rounds which sometimes below 1ms, sometimes above 1ms.

https://github.com/jonasrichard/erlang-bcrypt/blob/bb96149332c8c6b6135698dfbc21e19e554bc066/c_src/bcrypt_nif.c#L133

If I use some kernel gettime function, can it cause blocking?

- 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.

Thanks,
Richard

-- 
Richard Jonas
Erlang Solutions Hungary Kft

Address:
  Riverpark Office K.32
  Közraktár street 32. 3/1.
  1093 Budapest
  Hungary
Phone/fax:
  +36-1-7000-654
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20160706/e809b70c/attachment.htm>


More information about the erlang-questions mailing list