Profiling

From Crypto++ Wiki
Jump to: navigation, search

Profiling

For those using gprof (and who built with -pg), run cryptest.exe b to use Crypto++'s built in benchmarking to generate profiling data.

> cryptest.exe b > benchmark.html   # gmon.out written in PWD by instrumentation
> gprof -a -b cryptest.exe gmon.out > cryptest.exe.prof
> cat cryptest.exe.prof | more      # output below is baked for screen formatting
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 15.68     16.16    16.16  9325567     0.00     0.00  CryptoPP::Rijndael::Enc::AdvancedProcessBlocks
  5.97     22.31     6.15  1094386     0.00     0.00  CryptoPP::GF2NT::Multiply
  4.50     26.95     4.64   559773     0.00     0.00  CryptoPP::AlmostInverse
  3.73     30.79     3.84   547193     0.00     0.00  CryptoPP::GF2NT::MultiplicativeInverse
  2.54     33.41     2.62  1048576     0.00     0.00  CryptoPP::Salsa20_Policy::OperateKeystream
  2.50     35.99     2.58   320517     0.00     0.00  CryptoPP::RawDES::RawSetKey
  2.27     38.33     2.34   655360     0.00     0.00  CryptoPP::GCM_Base::AuthenticateBlocks
  ...

Memory Leaks

The Crypto++ mailing list occasionally receives messages concerning memory leaks from tools such as Purify and Bounds Checker. Under most circumstances, Crypto++ is leak free and the problem stems from one of two places - a legitimate leak (in the program using the library and not the library itself) and a false positive.

Reported Leak

The first leak is due to the programmer and is a valid item. The allocation occurs in the user's program but when the dump is printed, there is so much Crypto++ library code in the chain a programmer mistakenly claims the leak is with the library.

If you feel the library is truly leaking, please file a Bug Report. Before reporting, you should run cryptest v under the tool as a base case.

False Positive

The second leak is a false positive due to a tool reporting a leak where there is no leak. For example, in the past, BoundsChecker would report a C++ library object leaked even though the object was reclaimed when the C++ library was shut down and the program exited. The problem was that the BoundsChecker dll was unloaded before the runtime library terminated.

In the Microsoft environment, Visual Studio will report a leak when using Run-Time Type Information (RTTI). Microsoft states the warning can be safely ignored in KB140670. Below is a typical example of the typeid() leak. Notice that the output occurs in pairs (for example, allocations 1336110 and 1336111).

Detected memory leaks!
Dumping objects ->
{1336111} normal block at 0x003AECA8, 30 bytes long.
Data: <class CryptoPP::> 63 6C 61 73 73 20 43 72 79 70 74 6F 50 50 3A 3A
{1336110} normal block at 0x003ABB28, 8 bytes long.
Data: <  : X   > A8 EC 3A 00 58 06 AB 00
{798888} normal block at 0x003AB918, 58 bytes long.
Data: <class CryptoPP::> 63 6C 61 73 73 20 43 72 79 70 74 6F 50 50 3A 3A
{798887} normal block at 0x00AB0658, 8 bytes long.
Data: <  :   : > 18 B9 3A 00 B8 B9 3A 00

Though the issue has been well know since Visual C++ 4.0 days, it does not appear that Microsoft will fix the false positive. See Memory leaks reported by debug CRT inside typeinfo.name().

Validating Library Memory Usage

After building the Crypto++ library, it is usually a good idea to verify the build with cryptest v. Claiming validation is a good idea is an understatement - the build must be validated. Validation is a perfect time to run other tools, such as Purify and Valgrind, against the executable.

$ ./cryptest.exe V
5.6.1
$ ./cryptest.exe v
Using seed: 1282115289


Testing Settings...

passed:  Your machine is little endian.
passed:  Your machine allows unaligned data access.
passed:  sizeof(byte) == 1
passed:  sizeof(word16) == 2
passed:  sizeof(word32) == 4
passed:  sizeof(word64) == 8
passed:  sizeof(word128) == 16
passed:  sizeof(hword) == 4, sizeof(word) == 8, sizeof(dword) == 16
passed:  hasMMX == 1, hasISSE == 1, hasSSE2 == 1, hasSSSE3 == 1, hasAESNI == 0, hasCLMUL == 0, isP4 == 0, cacheLineSize == 64, AESNI_INTRINSICS == 1

Testing operating system provided blocking random number generator...

passed:  it took 0 seconds to generate 16 bytes
passed:  16 generated bytes compressed to 18 bytes by DEFLATE

...

ESIGN validation suite running...

passed    signature key validation
passed    signature and verification
passed    checking invalid signature
passed    verification check against test vector
Generating signature key from seed...
passed    signature key validation
passed    signature and verification
passed    checking invalid signature

All tests passed!

Test ended at Wed Aug 18 03:08:10 2010
Seed used was: 1282115289

Uninitialized Memory

Random pools can use unintialized memory as a source of entropy. Before filing a report, please verify the usage is not related to a random source. Also see Vendors are Bad for Security.

Application Verifier

Application Verifier is a Microsoft tool which profiles an application. To use Application Verifier, add cryptest.exe to the application list. Then run cryptest v under the Visual Studio debugger.

Below is a run with Memory, Heaps, Dangerous APIs, and Dirty Stacks enabled. Dangerous APIs include original C runtime functions such as memcpy (we should now use memcpy_s). Dirty Stacks checks for the use of uninitialized variables. The log file is not shown since there are 0 errors and 0 warnings.

File:AppVerifier.png

Valgrind and Valkyrie

To validate with Valgrind, perform the following from the build directory. The build directory is required so that the Test Vectors are available during the self test.

cd cryptopp-5.6.0/
valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./cryptest.exe v

After a successful run, output should be similar to below. If new to Valgrind, 17992 is the process id of the test run.

==17992== Memcheck, a memory error detector.
==17992== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==17992== Using LibVEX rev 1884, a library for dynamic binary translation.
==17992== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==17992== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==17992== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==17992== For more details, rerun with: -v
==17992==
...
==17992==
==17992== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==17992== malloc/free: in use at exit: 0 bytes in 0 blocks.
==17992== malloc/free: 1,119,117 allocs, 1,119,117 frees, 60,533,882 bytes allocated.
==17992== For counts of detected errors, rerun with: -v
==17992== All heap blocks were freed -- no leaks are possible.


Valkyrie is a visual front end to Valgrind. Below is a typical run of cryptest using the Crypto++ test vectors.

Valkyrie.png