bcrypt uses unique salts per-password. The hash outputted by the bcrypt function is actually several delimited fields that have been joined into a single string.
This means that if multiple users use a common password like 'pass123', the hashes stored in the database will still each be unique. Any attacker trying to reverse all of the password hashes will have to reverse every single one individually in a targeted manner rather than using pre-computed rainbow tables or generating hashes from a wordlist and scanning the database for matching hashes.
General-purpose cryptographic hash functions like the (now-broken) MD5, SHA1, SHA256, etc. are designed to be computationally easy, ie. fast.
Salting protects against rainbow tables [1], but it doesn't change the fact that computing a SHA256 hash is fast.
Password hash functions like PBKDF2, bcrypt, scrypt, Argon2 are designed to be computationally expensive, to make a password-cracking endeavor take even longer.
Argon2, the winner of the Password Hashing Competition and the current state-of-the-art, for example, has two ready-made variants: Argon2d is more resistant to GPU cracking, while Argon2i is more resistant to time-memory tradeoff attacks [2].
bcrypt is significantly slower to compute. Something like 5 or 6 orders of magnitude slower. (se my other comment in here with numbers for cracking various hash types on an 8gpu rig...)
If X is millions (or even billions), maybe, but you shouldn't. Just use one of the real password algorithms. Never ever roll your own hashing system assuming it's secure enough. It won't be.
Of course. I just wanted to get an idea of the reasons without going too much into mathematical details. For projects I would just use argon 2 or bcrypt.
This means that if multiple users use a common password like 'pass123', the hashes stored in the database will still each be unique. Any attacker trying to reverse all of the password hashes will have to reverse every single one individually in a targeted manner rather than using pre-computed rainbow tables or generating hashes from a wordlist and scanning the database for matching hashes.