cryptopp
cryptopp copied to clipboard
Add one line code to allow the data sink created on stack
If I understand correctly, the data sink in crypto++ needs to be created in the heap every time it is used. Just like this:
// ...
StreamTransformationFilter iDecryptor(*pDec, new StringSink(stResult)); // <-- new sink every time
iDecryptor.Put(static_cast<const BYTE*>(pData), nByteSize);
iDecryptor.MessageEnd();
// ... use stResult
Frequent new and delete operations have a certain degree of performance damage to the processing of a large number of small packets in a multi-threaded environment.
We can add a simple function to the Filter class:
BufferedTransformation* Deprive(void) { return m_attachment.release(); }
To eliminate all these new and delete operations:
// ...
ByteExSink skResult(btResult); // <--- create on stack
StreamTransformationFilter iDecryptor(*pDec, &skResult);
try
{
iDecryptor.Put(static_cast<const BYTE*>(pData), nByteSize);
iDecryptor.MessageEnd();
}
catch (...)
{
iDecryptor.Deprive(); // <--- prevent member_ptr delete it
throw;
}
iDecryptor.Deprive(); // <--- prevent member_ptr delete it
// ...
In our single-threaded test, the above optimization can bring about 8.5% performance improvement. The performance of multi-threaded testing can be increased by about 30%.
@asbai,
Well, I don't see the code for the ByteExSink
so I can't comment on what it is doing. I suspect you can do similar with:
char buf[512];
StreamTransformationFilter iDecryptor(*pDec, new ArraySink(buf, sizeof(buf)));
...
Or:
FixedSizeSecBlock<byte, 512> buf;
StreamTransformationFilter iDecryptor(*pDec, new ArraySink(buf, buf.size()));
...
@noloader Hi Jeffrey
Thanks for your reply
Well, I don't see the code for the ByteExSink so I can't comment on what it is doing. I suspect you can do similar with:
ByteExSink is not the point of this issue. It's just a class derived from StringSinkTemplate. Of course, it has also been optimized to avoid repeated allocation and release of memory.
What we want to eliminate is the new and delete of the Data Sink object itself. For example, new ArraySink(buf, sizeof(buf))
and the corresponding delete in your above code ... iDecryptor(*pDec, new ArraySink(buf, sizeof(buf)));
.
To be more specific with your example, we want to write code like this:
char buf[512];
ArraySink sink(buf, sizeof(buf)); // <---- create ArraySink ON STACK, NOT ON HEAP
StreamTransformationFilter iDecryptor(*pDec, &sink);
char buf[512];
ArraySink sink(buf, sizeof(buf)); // <---- create ArraySink ON STACK, NOT ON HEAP
StreamTransformationFilter iDecryptor(*pDec, &sink);
In this case, use a Redirector
:
char buf[512];
ArraySink sink(buf, sizeof(buf));
StreamTransformationFilter iDecryptor(*pDec, new Redirector(sink));
The Redirector
passes signals and data, but stops the ownership chain. Docs at https://www.cryptopp.com/wiki/Redirector.