Skip to content

Avoid binding functions to temporaries in random.py #131269

Open
@colesbury

Description

@colesbury

Feature or enhancement

The random module has a bunch of code that binds methods to temporary local variables like:

getrandbits = self.getrandbits

cpython/Lib/random.py

Lines 248 to 253 in 55815a6

getrandbits = self.getrandbits
k = n.bit_length()
r = getrandbits(k) # 0 <= r < 2**k
while r >= n:
r = getrandbits(k)
return r

I think this pattern dates back to 2001 (in d7b5e88). I think it was an optimization at one point, but now it's the opposite. Python optimizes method calls (in some sort since 3.7) so it's faster to use:

 k = n.bit_length() 
 r = self.getrandbits(k)  # 0 <= r < 2**k 
 while r >= n: 
     r = self.getrandbits(k) 
 return r 

Getting rid of this pattern seems to:

  1. Speed calls like random.randint() and random.shuffle() by about 10-15%
  2. Avoid some contention in multithreaded code because we are able to specialize the calls to LOAD_ATTR_METHOD_WITH_VALUES 1

This came up when looking at a variation of @pfmoore's code snippet: montecarlo.py

Linked PRs

Footnotes

  1. I think we should be able avoid contention even with this (anti-)pattern, but I'll write that up in a separate issue.

Metadata

Metadata

Assignees

Labels

performancePerformance or resource usagestdlibPython modules in the Lib dirtype-featureA feature request or enhancement

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions