by ChrisM [cmullins at winfessor dot com] posted on 2003/12/23 |
|
I’ve spent some time over the last few days trying to make my SSL / TLS enabled application perform a bit better. This has naturally resulted in looking pretty closely into the Mentalis library. To do this, I’ve been using the (free) Compuware Profiler for .NET found at http://makeashorterlink.com/?P5B8150E6
I’ve found a few areas in the Mentalis Libraries that would be considered “worst offenders”, and the optimization of which would result in 2x or larger performance gains. I’ve ignored the long running calls that are only called a few times, and instead concentrated on the calls that are made often.
In ServerHandshakeLayer.cs, the call to GetCertificateList takes a horribly, horribly horribly long time – this is by far the slowest portion of stream negotiation code. This ends up resolving down to the SspiProvider.CertOpenStore call in the Constructor for CertificateStore.cs. This looks like something that can be cached in a static variable.
In RecordLayer.cs, every call to WrapMessage (which gets called a lot) performs an Initialize on the m_LocalHasher variable. This Initialize is very slow, and can probably be eliminated.
In HMAC.cs, method ‘Initialize’. This method is called far more often than necessary and is very slow to run. In my test profile, which sent about 1000 message fragments over two TLS socket, this method was called 4339 times, and took a terribly long time each time it was called. Is there a way this can be cached? It’s called form both the class constructor, and from HashFinal.
In HMAC.cs, if any of the calls to TransformBlock or TransformFinalBlock can be eliminated, or combined, a large performance gain will result. Note that it takes longer to “Initialize” than it does to perform the transformations though.
In HMAC.cs, method ‘HashCore’ is called 8462 times (for 1000 message fragments), and is also very slow and looks as if most of it could be pre-calculated and cached.
|
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2004/01/12 |
|
Thanks for shaeing your findings. I'll look into your suggestions when I have some free time again.
As for calling the Initialize and HashCore methods several times per message, we're aware of this problem. Unfortunately there's no easy way to solve it because the .NET hashing algorithms do not support copying the internal state of a hash algorithm to a new instance. The SSL and TLS standards require that you keep a hash of all handshake messages, but at some points in the handshake, this hash must be finalized and used. In C++, you'd simply copy the internal state of the hash and finalize that copy. This can't be done in .NET, so you'll need to have multiple hashes and do most of the hashing several times. |