On Mon, 28 Sep 2015 at 14:57 Tuom Larsen <tuom.larsen@gmail.com> wrote:
Dear PyPy developers!

In CPython, a common idiom to copy a list is to use slice, as in:

    copy = original[:]

I noticed that under PyPy 2.6.0 it seems quite a bit slower than using
`list` constructor:

    from timeit import timeit
    print timeit('b = a[:]', 'a = list(range(100))')    # 0.0732719898224
    print timeit('b = list(a)', 'a = list(range(100))') # 0.00285792350769

Please, could some comment on what is the preferred way to copy a list
under PyPy? Should I try to avoid the "slice way"?

I don't get the same timings here:

enojb@it054759:~$ pypy -m timeit -s 'a = list(range(100))' 'b = a[:]'
1000000000 loops, best of 3: 0.00142 usec per loop
enojb@it054759:~$ pypy -m timeit -s 'a = list(range(100))' 'b = list(a)'
1000000000 loops, best of 3: 0.00109 usec per loop
 
So for me it's about the same. However if you look closer you'll see that it's about 1 nanosecond in either case. That's really a very short time. Why is so short? I guess because it's not really copying the lists. If I try with a much bigger list it takes the same time:

enojb@it054759:~$ pypy -m timeit -s 'a = list(range(1000000))' 'b = a[:]'
1000000000 loops, best of 3: 0.00142 usec per loop
enojb@it054759:~$ pypy -m timeit -s 'a = list(range(1000000))' 'b = list(a)'
1000000000 loops, best of 3: 0.00105 usec per loop

I would guess that the actual copy has somehow been optimised away. If I make the expression do some actual work instead of just copying a list then the differences are insignificant:

enojb@it054759:~$ pypy -m timeit -s 'a = list(range(100))' 'b = sum(a[:])'
1000000 loops, best of 3: 0.212 usec per loop
enojb@it054759:~$ pypy -m timeit -s 'a = list(range(100))' 'b =  sum(list(a))'
1000000 loops, best of 3: 0.205 usec per loop

So I wouldn't worry about how many nanoseconds the copy takes. Finish your application and then if the difference between slice/list copy actually affects whole application performance in a significant way then this question may be worth considering.

Until then just code it whichever way seems clearest to you. Bear in mind that the two are not equivalent since b[:] will return a tuple if b is a tuple, or a range if b is a range etc.

--
Oscar