I've done microbenchmark of SecureRandom to test this.

The CPU was Intel(R) Core(TM) i7-3537U CPU @ 2.00GHz, 2 core, 4 threads. OS is Linux 3.13.0-36-generic #63-Ubuntu SMP Wed Sep 3 21:30:07 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux.

The test instantiates one SecureRandom per thread and generate 1MB of random numbers, while measuring the time to do this. This run gets repeated 100 times to measure the variance of each run. Unit of measurement is ns.

In multi-threaded tests, the above gets run concurrently. The usual warm-up runs and post-measurement is inserted to make sure all the threads measure their performances while all the other threads are fully running.

The first one uses new SecureRandom() which selects NativePRNG:

single thread, 1 instance
Provider=SUN version 1.6, SPI=sun.security.provider.NativePRNG@2626d4f1
average=125,274,140, stddev=4,173,778
average=123,310,918, stddev=1,378,205
average=123,572,870, stddev=1,193,628

2 threads, 2 instances
Provider=SUN version 1.6, SPI=sun.security.provider.NativePRNG@37e893df
average=279,906,854, stddev=152,013,543
average=297,470,998, stddev=141,156,000

4 threads, 4 instances
Provider=SUN version 1.6, SPI=sun.security.provider.NativePRNG@67386000
average=481,466,668, stddev=0
average=548,326,932, stddev=0
average=618,292,518, stddev=0
average=698,000,865, stddev=185,175,894

It clearly shows the effect of contended global lock, even at 2 threads. CPU usage monitor also clearly indicates that the program fails to keep CPU pegged at 100%.

This next one uses SecureRandom.getInstance("SHA1PRNG)

1 thread
Provider=SUN version 1.6, SPI=sun.security.provider.SecureRandom@13d4c61c
average=20,976,505, stddev=1,052,441

2 threads, 2 instances
Provider=SUN version 1.6, SPI=sun.security.provider.SecureRandom@12b82368
average=29,316,610, stddev=7,856,792
average=29,675,002, stddev=7,529,021

4 threads, 4 instances
Provider=SUN version 1.6, SPI=sun.security.provider.SecureRandom@2cb0ce8f
average=42,3804,33, stddev=4,039,875
average=42,866,789, stddev=4,043,125
average=42,205,430, stddev=5,275,983
average=45,091,333, stddev=4,840,461

Here, not only the execution is considerably faster, but it scales much better. All 4 cores are kept 100% busy during the 4 thread test.

In search of other faster CRPRNG, I've also tried AESCountingRNG:

1 thread, AESCounterRNG
average=18,537,563, stddev=1,545,647

2 threads, 2 instances
average=24,666,657, stddev=2,966,315
average=24,755,655, stddev=2,946,206

4 threads, 4 instances
average=32,876,768, stddev=3,681,410
average=36,600,687, stddev=3,410,178
average=37,669,234, stddev=3,579,337
average=37,598,152, stddev=3,536,743

This is somewhat faster than SHA1PRNG. All 4 cores are kept busy during the 4 thread test.

Finally, what about the performance of /dev/urandom? I've used the following shell script to measure:

while true; do time dd if=/dev/urandom of=/dev/null bs=1MB count=1000; done

Single threaded:

1000000000 bytes (1.0 GB) copied, 71.471 s, 14.0 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 71.50s system 100% cpu 1:11.47 total
1000000000 bytes (1.0 GB) copied, 71.3007 s, 14.0 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 71.36s system 100% cpu 1:11.30 total
1000000000 bytes (1.0 GB) copied, 71.1508 s, 14.1 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 71.21s system 100% cpu 1:11.15 total

2 threads:

1000000000 bytes (1.0 GB) copied, 133.55 s, 7.5 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.01s user 133.64s system 100% cpu 2:13.55 total
1000000000 bytes (1.0 GB) copied, 133.243 s, 7.5 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 133.33s system 100% cpu 2:13.24 total
1000000000 bytes (1.0 GB) copied, 134.352 s, 7.4 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 134.43s system 100% cpu 2:14.35 total

4 threads:

1000000000 bytes (1.0 GB) copied, 353.65 s, 2.8 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 348.54s system 98% cpu 5:53.65 total
1000000000 bytes (1.0 GB) copied, 354.961 s, 2.8 MB/s
dd if=/dev/urandom of=/dev/null bs=1MB count=1000  0.00s user 348.84s system 98% cpu 5:54.97 total

14MB/sec translates to about 70,000,000ns per MB. So this is already considerably slower than SHA1PRNG. It is also obvious that /dev/urandom doesn't scale, although it is worth noting that CPUs are kept 100% busy during this experiment.

Based on this, I think we should just change trilead code to use SHA1PRNG by default.

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators.
For more information on JIRA, see: http://www.atlassian.com/software/jira

--
You received this message because you are subscribed to the Google Groups "Jenkins Issues" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jenkinsci-issues+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to