[Python-ideas] namedtuple with ordereddict

Terry Reedy tjreedy at udel.edu
Wed Jul 19 15:06:08 EDT 2017


On 7/19/2017 12:10 PM, Giampaolo Rodola' wrote:
> 
> 
> On Wed, Jul 19, 2017 at 5:20 PM, Tim Peters 
> <tim.peters at gmail.com 
> <mailto:tim.peters at gmail.com>> wrote:
> 
>     [Giampaolo Rodola' <g.rodola at gmail.com
>     <mailto:g.rodola at gmail.com>>]
>     > Still much slower (-4.3x) than plain tuples though:
>     >
>     > $ python3.7 -m timeit -s "import collections; Point => collections.namedtuple('Point', ('x', 'y'));" "Point(5, 11)"
>     > 1000000 loops, best of 5: 313 nsec per loop
>     >
>     > $ python3.7 -m timeit "tuple((5, 11))"
>     > 5000000 loops, best of 5: 71.4 nsec per loop
> 
>     I believe this was pointed out earlier:  in the second case,
> 
>     1. (5, 11) is built at _compile_ time, so at runtime it's only
>     measuring a LOAD_FAST to fetch it from the code's constants block.
> 
>     2. The tuple() constructor does close to nothing when passed a tuple:
>     it just increments the argument's reference count and returns it.
> 
>      >>> t = (1, 2)
>      >>> tuple(t) is t
>     True
> 
>     In other words, the second case isn't measuring tuple _creation_ time
>     in any sense:  it's just measuring how long it takes to look up the
>     name "tuple" and increment the refcount on a tuple that was created at
>     compile time.
> 
> 
> Oh right, I didn't realize that, sorry. Should have been something like 
> this instead:
> 
> $ python3.7 -m timeit -s "import collections; Point = 
> collections.namedtuple('Point', ('x', 'y')); x = [5, 1]" "Point(*x)"
> 1000000 loops, best of 5: 311 nsec per loop
> 
> $ python3.7 -m timeit -s "x = [5, 1]" "tuple(x)"
> 5000000 loops, best of 5: 89.8 nsec per loop

I thing "x,y = 5, 1" in the setup and "Point(x,y)", and "(x,y)" better 
model real situations.  "x,y" cannot be optimized away but reflects how 
people would construct a tuple given x and y.

On my Win10 machine with 3.7 with debug win32 build (half as fast as 
without debug), I get

F:\dev\3x>python -m timeit -s "import collections as c; Point = 
c.namedtuple('Point',('x','y')); x,y=5,1", "Point(x,y)"
200000 loops, best of 5: 1.86 usec per loop

F:\dev\3x>python -m timeit -s "x,y=5,1", "(x,y)"
2000000 loops, best of 5: 156 nsec per loop

If one starts with a tuple, then the Point call is pure extra overhead. 
If one does start with a list, I get 1.85 usec and 419 nsec



> -- 
> Giampaolo - http://grodola.blogspot.com
> 
> 
> 
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 


-- 
Terry Jan Reedy



More information about the Python-ideas mailing list