openlang

Tuple construction trails lists with Python 3.14

I've found that constructing a list beats constructing a tuple on Python 3.14. For my computer, this begins at roughly ~20 elements.

That seems rather intriguing. What made this possible? Could tuples receive that optimization as well?

The conversation continues 2

Follow the reasoning
  1. Permalink

    Would you provide some more specifics, including your actual benchmark code (lists and tuples can each be constructed several ways), the measurement method and the figures you got? Were older Python releases different, too?

    I've investigated a similar question myself, looking at these four alternatives:

    1. list(values)
    2. [*values]
    3. tuple(values)
    4. (*values,)

    As I recoll, 2 beat 1, whereas 3 beat 4, which seemed strange. I've forgotten what conclusion I reached there…

  2. Permalink

    I've just repeated the test using values = itertools.repeat(None, 2**20):

     4.02 ± 0.04 ms  list(values)
     3.97 ± 0.03 ms  [*values]
     4.76 ± 0.08 ms  tuple(values)
     7.91 ± 0.12 ms  (*values,)
    
    Python: 3.13.0 (main, Nov 12 2025, 14:27:38) [GCC 15.2.1 20250820]

    script

    from timeit import timeit
    from statistics import mean, stdev
    import random
    import sys
    
    prelude = """
    from itertools import repeat
    values = repeat(None, 2**20)
    """
    
    expressions = ['list(values)', '[*values]',
                   'tuple(values)', '(*values,)']
    
    samples = {expression: [] for expression in expressions}
    for trial in range(120):
        for expression in random.sample(expressions, len(expressions)):
            elapsed = timeit(expression, prelude, number=1)
            samples[expression].append(elapsed)
    for expression in expressions:
        fastest = [elapsed * 1e3 for elapsed in sorted(samples[expression])[:6]]
        print(f'{mean(fastest):5.2f} ± {stdev(fastest):3.2f} ms ', expression)
    
    print('\nPython:', sys.version)

    Run This Example!

    (The advantage of [*values] over list(values) applied to small iterables, since the interpreter can process [*values] directly as syntax.)

    Regardless, my hazy recollection is that constructing tuples favors small ones, since those are what people typically need. Generally you'd choose a list rather than fill a tuple with lots of objects. Improving the small-input case can also make larger inputs slower.

Other sides of the same question

  1. Which Rust execution benchmarks are commonly used?

    Hello folks, I'm new to developing the Rust compiler and currently trying my hand at implementing compiler optimizations. Cou…

    Replies 2Latest activity rust