Reduce memory usage
See original GitHub issueI was looking through the source code of the library, and noticed that there is quite some room to reduce the amount of memory allocated for certain operations.
I ran benchmarks (source code attached) for the (I think) most commonly used public methods, and came up with these results.
Obviously a large part of the runtime and memory usage is inherent to the algorithm itself, but I do believe that some optimizations might be useful to reduce unnecessary allocations.
Things I noticed at first glance:
- StringBuilders are used as scratch buffers, preallocating might be possible.
- The hash interrogation regexes generate a lot of garbage, a fast path for
PasswordNeedsRehash
could be added to improve this scenario. A simple custom parser could improve this significantly. - .NET Standard 2.1 has a lot of Span based API’s that could be used to implement optimized paths if the consumer is compatible.
Are you interested in taking PR’s for this?
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363
Intel Core i7-3632QM CPU 2.20GHz (Ivy Bridge), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.101
[Host] : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT
DefaultJob : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT
Method | text | hash | value | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
---|---|---|---|---|---|---|---|---|---|---|
GenerateSalt | ? | ? | ? | 748.4 ns | 5.92 ns | 4.95 ns | 0.2155 | - | - | 680 B |
PasswordNeedsRehash | ? | ? | ? | 3,395.1 ns | 37.28 ns | 31.13 ns | 0.4196 | - | - | 1328 B |
VerifyPassword | **** | $2a$0(…)eX1s. [60] | ? | 7,105,149.9 ns | 43,366.64 ns | 36,213.11 ns | - | - | - | 10064 B |
HashPassword | ? | ? | **** | 7,015,698.7 ns | 48,091.09 ns | 44,984.44 ns | - | - | - | 10405 B |
VerifyPassword | abcde(…)vwxyz [26] | $2a$0(…)QhstC [60] | ? | 7,090,475.1 ns | 18,558.79 ns | 15,497.43 ns | - | - | - | 10174 B |
HashPassword | ? | ? | abcde(…)vwxyz [26] | 7,154,595.2 ns | 85,278.99 ns | 79,770.02 ns | - | - | - | 10515 B |
[MemoryDiagnoser]
public class Benchmarks
{
[Benchmark]
public string GenerateSalt()
=> BCrypt.GenerateSalt(10);
[Benchmark]
public bool PasswordNeedsRehash()
=> BCrypt.PasswordNeedsRehash("$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.", 10);
[Benchmark]
[Arguments("")]
[Arguments("abcdefghijklmnopqrstuvwxyz")]
public string HashPassword(string value)
=> BCrypt.HashPassword(value, "$2a$06$DCq7YPn5Rq63x1Lad4cll.", true, HashType.SHA384);
[Benchmark]
[Arguments("", "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.")]
[Arguments("abcdefghijklmnopqrstuvwxyz", "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC")]
public bool VerifyPassword(string text, string hash)
=> BCrypt.Verify(text, hash);
}
Update: Aligned benchmarks to all use workfactor 6 hashes
Issue Analytics
- State:
- Created 4 years ago
- Comments:29 (8 by maintainers)
Top Results From Across the Web
How to Free Up RAM and Reduce RAM Usage on Windows
An easy way to reduce RAM usage is to prevent programs you never use anyway from consuming it. Apps you haven't opened in...
Read more >How to decrease RAM usage?
Turn your device off and on Check which programs are draining your RAM Cut down background apps Use less resource-instensive apps Close apps...
Read more >How to Free Up RAM in Windows 11
6 ways to free up RAM on your Windows 11 · Task Manager · Uninstall unused programs · Reduce background applications · Clean...
Read more >How To Stop High RAM Usage in Windows 10
1. Close unused background programs 2. Disable startup programs 3. Uninstall programs you no longer use 4. Check your computer for Malware 5....
Read more >10 Effective Ways To Lower RAM Usage On Windows
10 Effective Ways to Lower RAM Usage on Windows ; Press Ctrl + Alt + Delt, then select Task Manager. Once the Task...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Awesome, glad to be able to help. The span PR could be done without Span by moving the ‘_lr’ array into a private field and initializing it instead of allocating a new array each iteration. Should give roughly the same order of savings. Not sure if there are any security implications when doing that tho.
Shouldn’t really matter as you can then control when the array is cleared instead of leaving it up to the GC.
Yup