Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache fetching rotated key names #498

Merged
merged 5 commits into from
Feb 17, 2022

Conversation

Lagovas
Copy link
Collaborator

@Lagovas Lagovas commented Feb 16, 2022

  • added caching results from store.getCachedHistoricalPrivateKeyFilenames call that reads folder every time when decryption keys are requested.
  • due to []byte type used in our in-memory cache with interface Get(id[]byte)[]byte/Set([]byte, []byte), to cache results used msgpack as more efficient way to serialize/deserialize than gob or split/join strings.
  • struct for msgpack placed in internal package because msgpack can serialize only public structs. And this struct shouldn't be public and exported from keystore/filesystem package. So to hide and encapsulate this struct, it placed to internal that accessible from keystore/filesystem, but not accessed from top-level packages.
  • added benchmarks that prove efficient serialization in comparison with simple strings operations
  • because of checked profiling data that this function removed from call graph, also updated docker-compose and added tmpfs usage for postgresql that decreased time of tests and works more predictable. It cannot be used for keystore because docker doesn't support tmpfs volumes shared between containers.
  • also in prifling data found that we have extra allocations in getSymmetricKeys due to small start allocation keys := make([][]byte, 0, 1) when usually may be at least 2 keys (current and 1 rotated). So increased to 4. It is not increase memory usage because it's allocates +3 structs with 3 int fields (SliceHeader with ptr + length + capacity), so it's just 3 * 24 bytes (72) instead of 24.

Checklist

…lls to storage backend

some optimizations related to compiling filenames
cache poison record keys and optimize fetching with removed extra storage checks
Co-authored-by: Anatolii Lishchynskyi <anatolii.lishchynskyi@cossacklabs.com>
@@ -387,12 +390,55 @@ func (store *KeyStore) GetPublicKeyFilePath(filename string) string {
return fmt.Sprintf("%s%s%s", store.publicKeyDirectory, string(os.PathSeparator), filename)
}

// use key started with "." (dot) because it's invalid character for clientID that generally stored in cache and
// it will not intersect with other keys
const cacheKeySuffix = ".historical."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on how you use it, it's more like a cacheKeyPrefix 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, renamed

@iamnotacake
Copy link
Contributor

We probably could make keystore cache interface to be []byte <-> interface{} instead of []byte <-> []byte, but I guess existing scenario (caching bytes array) is more common in practice, and using interface would need type casting on each access, so probably some little overhead will be involved

// goos: linux
// goarch: amd64
// pkg: github.com/cossacklabs/acra/keystore/filesystem
// cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you lock CPU frequency at this specific (or some other) value when benchmarking?
BTW, to get more precise results, instead of closing other apps, sending them SIGSTOP will also do the trick 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what we need here such precise benchmarks? there are 10^10 difference between approaches. you think such improvements may change general picture of that and we should spent time for that?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just simple benchmark to show other developers who will read code and think: why you used this serialization algo instead of some more simple from std. and to allow everyone reproduce by one command on their machine to be sure

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just saying what comes in mind. Here we clearly see that msgpack is much better, that's enough.

BTW, if you wanted to try something like this, I got a shell function to set min/max frequencies, at least it worked for some Intel laptop CPU

set-cpu-freq-min-max() {
	[[ $1 > 0 && $2 > 0 ]] || { echo "$0 <min_freq_KHz> <max_freq_KHz>"; return }
	echo $1 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq
	echo $2 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq
}

@Lagovas
Copy link
Collaborator Author

Lagovas commented Feb 16, 2022

We probably could make keystore cache interface to be []byte <-> interface{} instead of []byte <-> []byte, but I guess existing scenario (caching bytes array) is more common in practice, and using interface would need type casting on each access, so probably some little overhead will be involved

I though about it... but I don't want to use reflection here because it more type checks, more code like:

value, ok := cache.Get(key)
if !ok{...}
typedValue, ok := value.([]string}
if !ok {...}

for now, it is enough to convert everything to bytes, imho. you can add more arguments why we should change this approach.

@Lagovas Lagovas merged commit 0ee0df1 into master Feb 17, 2022
@Lagovas Lagovas deleted the lagovas/T2476-cache-fetching-rotated-key-names branch February 17, 2022 00:27
Lagovas added a commit that referenced this pull request Feb 17, 2022
@Lagovas Lagovas mentioned this pull request Feb 17, 2022
7 tasks
Lagovas added a commit that referenced this pull request Feb 17, 2022
Lagovas added a commit that referenced this pull request Feb 17, 2022
Lagovas added a commit that referenced this pull request Feb 17, 2022
* fix caching poison record keypair after last updates in #498 and
add unit-tests that catch this issues
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants