cryptopp icon indicating copy to clipboard operation
cryptopp copied to clipboard

Add one line code to allow the data sink created on stack

Open asbai opened this issue 3 years ago • 2 comments

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 avatar Oct 20 '21 19:10 asbai

@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()));
...

The FixedSizeSecBlock docs are available here and here.

noloader avatar Oct 23 '21 10:10 noloader

@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);

asbai avatar Oct 24 '21 12:10 asbai

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.

noloader avatar Jun 25 '23 23:06 noloader