Python Find the fastest way to access a property for performance

eye-catch Python

In most cases, we don’t have to consider about performance because our program runs fast enough. But we sometimes find a feature that processes slowly. The first thing that we must do is analize to know where the bottle neck is. This post might help you to know which structure is the fastest way if you find accessing properties a lot of times causes the performance issue.

You might run into the problem when you need to read properties over the for-loop with big numbers of array.

Sponsored links

Code for the performance check

I used timeit to compare the processing speed. All of structures have the same data and size.

from typing import List
import timeit
from collections import namedtuple

KeyValueTuple = namedtuple('KeyValueTuple', ["k", "v"])


class Pair:
    def __init__(self, val) -> None:
        self.value1 = val
        self.value2 = str(val)


SIZE = 99999

pairs = []
tuples = []
key_value_tuples: List[KeyValueTuple] = []
my_dict = {}
array_list = []

for i in range(SIZE):
    pairs.append(Pair(i))
    tuples.append((i, str(i)))
    key_value_tuples.append(KeyValueTuple(i, str(i)))
    my_dict[i] = str(i)
    array_list.append([i, str(i)])


def run_pairs():
    for pair in pairs:
        a = pair.value1
        b = pair.value2


def run_pairs_getattr():
    for pair in pairs:
        a = getattr(pair, "value1")
        b = getattr(pair, "value2")


def run_tuples():
    for tuple in tuples:
        a = tuple[0]
        b = tuple[1]


def run_named_tuples():
    for tuple in key_value_tuples:
        a = tuple.k
        b = tuple.v


def run_dict_items():
    for key, value in my_dict.items():
        a = key
        b = value


def run_dict_keys():
    for key in my_dict.keys():
        a = key
        b = my_dict[key]


def run_dict_list_dict():
    for key in list(my_dict):
        a = key
        b = my_dict[key]


def run_dict_list_items():
    for pair in list(my_dict.items()):
        a = pair[0]
        b = pair[1]


def run_array_list():
    for array in array_list:
        a = array[0]
        b = array[1]


# fmt: off
LOOP_COUNT = 100
print(timeit.timeit("run_pairs()", "from __main__ import run_pairs", number=LOOP_COUNT))                    
print(timeit.timeit("run_pairs_getattr()", "from __main__ import run_pairs_getattr", number=LOOP_COUNT))    
print(timeit.timeit("run_tuples()", "from __main__ import run_tuples", number=LOOP_COUNT))                  
print(timeit.timeit("run_named_tuples()", "from __main__ import run_named_tuples", number=LOOP_COUNT))
print(timeit.timeit("run_dict_items()", "from __main__ import run_dict_items", number=LOOP_COUNT))          
print(timeit.timeit("run_dict_keys()", "from __main__ import run_dict_keys", number=LOOP_COUNT))            
print(timeit.timeit("run_dict_list_dict()", "from __main__ import run_dict_list_dict", number=LOOP_COUNT))  
print(timeit.timeit("run_dict_list_items()", "from __main__ import run_dict_list_items", number=LOOP_COUNT))
print(timeit.timeit("run_array_list()", "from __main__ import run_array_list", number=LOOP_COUNT))          
Sponsored links

Dict is the fastest structure to access a property

I tested with LOOP_COUNT = 10 several times because CPU usage at the running might influence the result.

PC1 fast (Windows10, Core i7-9850H, 32 GB)

repeat count10101010100
run_pairs0.14750.12100.12120.15691.2793
run_pairs_getattr0.21250.20470.19740.20531.9415
run_tuples0.13720.12150.11840.13261.0986
run_named_tuples0.10640.11740.11180.13281.2105
run_dict_items0.07060.06360.06730.08060.6058
run_dict_keys0.08210.09340.08500.10890.9272
run_dict_list_dict0.10040.09630.09690.10521.1009
run_dict_list_items0.24210.22470.22820.25492.3844
run_array_list0.12830.11460.11660.15311.2289

PC2 slow (Linux Mint 21 64-bit, Core i5-6200U, 8 GB)

repeat count10101010100
run_pairs0.18720.18880.19350.26311.9236
run_pairs_getattr0.29640.31640.28350.44952.5526
run_tuples0.12860.12560.13320.16661.0770
run_named_tuples0.16350.16280.15580.21041.4255
run_dict_items0.13530.13020.12920.17231.1259
run_dict_keys0.16640.16800.16380.22201.4882
run_dict_list_dict0.17590.17920.17550.24271.6271
run_dict_list_items0.26200.26120.26710.32672.5208
run_array_list0.13370.13150.13520.17681.2371

Dict is the fastest way to access a property on a faster PC but tuple is the fastest on a slower PC. This is an interesting result.

This performance check should be done on the environment where your application actually runs but basically using Dict is one of the reasonable choices.

Comments

Copied title and URL