We are using the *_ex variant of several OpenSSL functions which cause us more harm than good in terms of performance:
EVP_MD_CTX_copy_ex requires an initialized context, but we always have an uninitialized context at that point, so we have to call EVP_DigestInit_ex before it. On the other hand, EVP_MD_CTX_copy initializes the context for us in one call.
EVP_DigestInit_ex does not reset the context, but EVP_DigestInit does, so we can avoid calling EVP_MD_CTX_reset on our side.
EVP_DigestFinal_ex does not reset the context, but EVP_DigestFinal does, so we can avoid calling EVP_MD_CTX_reset on our side.
Taking into account that each cgo call overhead is ~80ns, getting rid of 3 cgo calls can make a difference when hashing small messages:
name old time/op new time/op delta
Hash8Bytes-4 1.93µs ± 1% 1.23µs ± 3% -36.46% (p=0.000 n=9+10)
name old speed new speed delta
Hash8Bytes-4 4.14MB/s ± 1% 6.51MB/s ± 3% +57.38% (p=0.000 n=9+10)
name old memory/op new memory/op delta
Hash8Bytes-4 0.00B 0.00B ~ (all equal)
name old allocs/op new allocs/op delta
Hash8Bytes-4 0.00 0.00 ~ (all equal)
We are using the
*_ex
variant of several OpenSSL functions which cause us more harm than good in terms of performance:EVP_MD_CTX_copy_ex
requires an initialized context, but we always have an uninitialized context at that point, so we have to callEVP_DigestInit_ex
before it. On the other hand,EVP_MD_CTX_copy
initializes the context for us in one call.EVP_DigestInit_ex
does not reset the context, butEVP_DigestInit
does, so we can avoid callingEVP_MD_CTX_reset
on our side.EVP_DigestFinal_ex
does not reset the context, butEVP_DigestFinal
does, so we can avoid callingEVP_MD_CTX_reset
on our side.Taking into account that each cgo call overhead is ~80ns, getting rid of 3 cgo calls can make a difference when hashing small messages: