Project

General

Profile

Feature #4430

libuuid could cache /dev/random

Added by Robert Mustacchi over 5 years ago. Updated over 5 years ago.

Status:
Resolved
Priority:
Normal
Assignee:
-
Category:
lib - userland libraries
Start date:
2013-12-24
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:

Description

In doing some work, we encountered the fact that uuid generation on illumos is much slower than on other platforms. To recreate this, simply:

$ git clone git://github.com/mcavage/node-libuuid.git
$ cd node-libuuid
$ node-gyp rebuild
$ npm test

The following are notes from Jerry's investigations. I went back to my full set of syscall aggregations and see this:

  read                                              
           value  ------------- Distribution ------------- count    
              -1 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1000006  
               1 |                                         2        
               2 |                                         0        

  open                                              
           value  ------------- Distribution ------------- count    
              -1 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2000015  
               1 |                                         3        
               2 |                                         0        

  close                                             
           value  ------------- Distribution ------------- count    
              -1 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2000023  
               1 |                                         3        
               2 |                                         0        

So even though the time is not high, we can see that we are doing an open/read on something each time we generate a uuid. I aggregated the files we're opening.

  /dev/kstat                                                        1
  /lib/libc.so.1                                                    1
  /lib/libdl.so.1                                                   1
  /lib/libkstat.so.1                                                1
  /lib/libm.so.2                                                    1
  /lib/libnsl.so.1                                                  1
  /lib/libpthread.so.1                                              1
  /lib/libsendfile.so.1                                             1
  /lib/libsocket.so.1                                               1
  /lib/libumem.so.1                                                 1
  /lib/libumem_trampoline.so.1                                      1
  /lib/libuuid.so.1                                                 1
  /opt/local/gcc47/i386-sun-solaris2.11/lib/./libgcc_s.so.1                1
  /opt/local/gcc47/i386-sun-solaris2.11/lib/./libstdc++.so.6                1
  /opt/local/lib/libcrypto.so.1.0.0                                 1
  /opt/local/lib/libssl.so.1.0.0                                    1
  /root/node-libuuid/build/Release/uuid.node                        1
  /var/ld/ld.config                                                 1
  /dev/urandom                                                2000000

So it is virtually a certainty that the 2m calls to urandom is what is taking all of the time.

I changed the C program to only open /dev/urandom once, do 1m reads, and close the fd. When I run this in the zone I get:

[root@443d424f-ec90-cfc4-ca05-8daf130a167e ~]# time ./rand

real 0m1.762s
user 0m0.221s
sys 0m1.540s

So it seems like the fact that node is opening /dev/urandom 2m times is the big issue here. I changed the test program to not do any reads and simply open/close /dev/urandom 2m times, as we see in the dtrace result.

[root@443d424f-ec90-cfc4-ca05-8daf130a167e ~]# time ./rand       

real    0m14.426s
user    0m1.129s
sys     0m13.290s

The open of /dev/urandom happens in libuuid which actually opens and closes the dev twice per uuid. I changed the code to only open the dev once and got a significant speedup. In the graphite-dev zone with LD_LIBRARY_PATH pointing to the new library:

> libuuid@0.1.2 test /root/node-libuuid
> node test/t1.js

1000000 over 3.256 seconds
999999.9976493253create/second

So this is a 5-10x speedup.

As an additional change, I added code to cache 64K bytes of random data to reduce the number of reads to /dev/urandom. This helps a little bit and it makes repeated runs a lot more consistent on the elapsed time:

> libuuid@0.1.2 test /root/node-libuuid
> node test/t1.js

1000000 over 2.445 seconds
999999.998234836create/second

History

#1

Updated by Robert Mustacchi over 5 years ago

  • Status changed from New to Resolved

Resolved in 84615402a46a91be66843bd64e4fb72642b06e9d.

Also available in: Atom PDF