hedyorg / hedy

Hedy is a gradual programming language to teach children programming. Gradual languages use different language levels, where each level adds new concepts and syntactic complexity. At the end of the Hedy level sequence, kids master a subset of syntactically valid Python.
https://www.hedy.org
European Union Public License 1.2
1.29k stars 284 forks source link

bcrypt work factor is killing our poor Heroku box #387

Closed rix0rrr closed 3 years ago

rix0rrr commented 3 years ago

We have bcrypt at the default work factor of 12, which is a bit steep for our single-core Heroku box.

Right now, any bcrypt hash operation takes about ~300ms:

$ time python -c 'import bcrypt; bcrypt.hashpw(bytes("asdf1234", "utf-8"), bcrypt.gensalt())'

real    0m0.354s
user    0m0.340s
sys 0m0.012s

Keeping in mind that the box has only a single processor and so can only do one thing at a time, 3 logins/signups/password resets/any bcrypt operation will block anyone else from submitting a program to the web server or doing anything else for a full second [0]. This is already leading to noticeable load and latency spikes on the metrics dashboard.

Yes, we could spring for more cores, but we're on a bit of a budget and would like to stretch our single-core machine as far as it'll go.

We should reduce the work factor of the bcrypt operations to something more reasonable, like 9:

~ $ time python -c 'import bcrypt; bcrypt.hashpw(bytes("asdf1234", "utf-8"), bcrypt.gensalt(rounds=9))'

real    0m0.084s
user    0m0.080s
sys 0m0.000s

This is going to require some code to check the load factor of a user's existing salt and regenerate, re-hash and re-store their password if their current salt does not match our current desired work factor.

[0] Not entirely of course, because we have a couple of threads running and not all work is purely CPU-bound, some of the work is I/O bound like reading files from disk or reading things from DynamoDB... but the core work of the Hedy server is compiling code which is also CPU bound so we're definitely contending with the main purpose of the web app.

fpereiro commented 3 years ago

Hi @rix0rrr !

This can definitely give some oxygen to the Heroku box. While I'd rather use the default load factor and I think we'll have to get multiple cores sooner than later, it could be worth to do this in the meantime.

If I understand correctly, the implementation would require:

Felienne commented 3 years ago

@fpereiro Yes those are exactly the steps that are needed Happy if you can take this up!

fpereiro commented 3 years ago

@Felienne will do!