[PM-3426] Make cipher decryption faster by running in parallel#2685
[PM-3426] Make cipher decryption faster by running in parallel#2685quexten wants to merge 5 commits intobitwarden:mainfrom
Conversation
|
Thank you for your contribution! We've added this to our internal Community PR board for review. |
vvolkgang
left a comment
There was a problem hiding this comment.
Good catch! Added one small note about the usage of .Result but, I believe we might have some additional quick wins here.
Before we get into that, we should take the opportunity and write a repeatable-ish performance test so we can have more confidence in our findings. For the time being this will probably be a new method / class in our Core.Tests and we can later look at an in-app test.
Checking with our devs and I'll circle back!
src/Core/Services/CipherService.cs
Outdated
| var decCiphers = parallelQuery | ||
| .Select(cipher => | ||
| { | ||
| return cipher.DecryptAsync().Result; |
There was a problem hiding this comment.
While I understand why the current approach led you here, we need to go Async All The Way, ie, not using .Result.
It's usually a great indicator that everything else needs to be refactored.
There was a problem hiding this comment.
Thanks for the article. I'm not too familiar with how c# handles async. I believe in this case it might not have been a problem, since every synchronous, blocking .Result is on a separate thread and thus has a different synchronization context, but I might also be wrong about this.
Either way, I've changed it now to use async only, so it should be fine now.
|
To get some more accurate numbers to this, I measured the time in emulator on my 10k cipher test account (using DateTime.Now). I think the numbers paint a pretty clear picture. (This is specifically only decryption time, getting the encrypted ciphers from storage using This is a ~200% speedup in emulator, likely more on actual devices. |
|
Closing. The native apps make this irrelevant. |
Type of change
Objective
With a lot of ciphers in the vault, opening the vault (unlock/login) takes quite long (~25 seconds for my 10k cipher test vault). One of the causes seems to be that the cipher decryption runs concurrently (through async await) but not in parallel.
This PR rewrites the cipher decryption logic a bit to be both more readable and to run in parallel. On my emulator device, this brought the decryption time down to ~15 seconds. (An improvement, but there might still be a bottleneck somewhere else, since not all CPU resources were fully utilized. On the other hand, the emulator might also hinder further parallelization).
Related:
bitwarden/mobile#579
Code changes
.AsParallel()to run the decryption in parallelScreenshots
Before you submit
dotnet format --verify-no-changes) (required)