Merge lp:~gz/bzr/trivial_urandom_uncalled into lp:bzr

Proposed by Martin Packman
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 6423
Proposed branch: lp:~gz/bzr/trivial_urandom_uncalled
Merge into: lp:bzr
Diff against target: 32 lines (+9/-12)
1 file modified
bzrlib/osutils.py (+9/-12)
To merge this branch: bzr merge lp:~gz/bzr/trivial_urandom_uncalled
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) Approve
Review via email: mp+87396@code.launchpad.net

Commit message

Simplify wrapping of os.urandom done by osutils

Description of the change

Peel back some of the layering around os.urandom done by osutils at module start time. It's worth avoiding reading the one byte to check the function works on windows, as the first call does expensive initialisation, notably advapi32.dll needs loading. That makes this one call account for 50-100ms on my windows box, where a simple command takes in the region of 400ms on hot caches.

With --profile-imports the change is from:
    143.5 103.6 ++ [osutils]bzrlib @ bzrlib.plugin:36
To:
     38.7 4.4 ++ [osutils]bzrlib @ bzrlib.plugin:36

The various users of osutils.rand_chars (fancy_rename, lockdir) mean commands that do real work will still need to pay this at a later stage.

Various notes:
* AttributeError from accessing 'urandom' on os not needed since Python 2.4
* NotImplementedError from nt.urandom not an issue with any supported windows versions
* Wrapping /dev/urandom serves no purpose since Python 2.4
* isinstance(os.urandom, types.BuiltinFunctionType) would be a better check but needs an import

Are there in fact any circumstances in which /dev/urandom will not be available that we want to support, or should I just go all the way and remove the Mersenne Twister fallback as well?

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

> Are there in fact any circumstances in which /dev/urandom will not be available that we want to support, or should I just go all the way and remove the Mersenne Twister fallback as well?

I have no idea what you mean by "the Mersene Twister fallback". Other than that, I think this is a reasonable change.

review: Approve
Revision history for this message
Martin Packman (gz) wrote :

> I have no idea what you mean by "the Mersene Twister fallback". Other than
> that, I think this is a reasonable change.

Using the random module (which gives pseudo-random output). Following the (mostly unrelated) python-dev thread, it seems a guess for one circumstance where this might be needed was right, in a chroot without /dev exposed (which is arguably a broken setup). If they go ahead with randomising the hash function on startup, this change won't be a win any more, but never mind.

<http://mail.python.org/pipermail/python-dev/2012-January/115263.html>

Revision history for this message
Martin Packman (gz) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/osutils.py'
2--- bzrlib/osutils.py 2012-01-02 08:22:01 +0000
3+++ bzrlib/osutils.py 2012-01-03 17:51:38 +0000
4@@ -945,19 +945,16 @@
5 return os.fstat(f.fileno())[stat.ST_SIZE]
6
7
8-# Define rand_bytes based on platform.
9-try:
10- # Python 2.4 and later have os.urandom,
11- # but it doesn't work on some arches
12- os.urandom(1)
13- rand_bytes = os.urandom
14-except (NotImplementedError, AttributeError):
15- # If python doesn't have os.urandom, or it doesn't work,
16- # then try to first pull random data from /dev/urandom
17+# Alias os.urandom to support platforms (which?) without /dev/urandom and
18+# override if it doesn't work. Avoid checking on windows where there is
19+# significant initialisation cost that can be avoided for some bzr calls.
20+
21+rand_bytes = os.urandom
22+
23+if rand_bytes.__module__ != "nt":
24 try:
25- rand_bytes = file('/dev/urandom', 'rb').read
26- # Otherwise, use this hack as a last resort
27- except (IOError, OSError):
28+ rand_bytes(1)
29+ except NotImplementedError:
30 # not well seeded, but better than nothing
31 def rand_bytes(n):
32 import random