import heapq
import random
import time
from dataclasses import dataclass
from collections import namedtuple
from typing import NamedTuple
# config
N = 100_000
random.seed(0)
keys = [
(
(-random.randint(0, 1000), -random.randint(0, 1000),
random.randint(0, 1000), -random.randint(0, 1000)),
i,
random.randint(0, 1000)
)
for i in range(N)
]
# raw tuple benchmark
def bench_tuple():
h = []
for entry in keys:
heapq.heappush(h, entry)
for _ in range(len(keys)):
heapq.heappop(h)
# namedtuple benchmark
TaskNT = namedtuple('TaskNT', ['key', 'taskId', 'userId'])
def bench_namedtuple():
h = []
for k, t, u in keys:
heapq.heappush(h, TaskNT(k, t, u))
for _ in range(len(keys)):
heapq.heappop(h)
# typing.NamedTuple benchmark
class TaskTNT(NamedTuple):
key: tuple
taskId: int
userId: int
def bench_typing_namedtuple():
h = []
for k, t, u in keys:
heapq.heappush(h, TaskTNT(k, t, u))
for _ in range(len(keys)):
heapq.heappop(h)
# standard dataclass benchmark
@dataclass(order=True)
class TaskDC:
key: tuple
taskId: int
userId: int
def bench_dataclass():
h = []
for k, t, u in keys:
heapq.heappush(h, TaskDC(k, t, u))
for _ in range(len(keys)):
heapq.heappop(h)
# dataclass with slots benchmark
@dataclass(order=True, slots=True)
class TaskDCS:
key: tuple
taskId: int
userId: int
def bench_dataclass_slots():
h = []
for k, t, u in keys:
heapq.heappush(h, TaskDCS(k, t, u))
for _ in range(len(keys)):
heapq.heappop(h)
benchmarks = [
('tuple', bench_tuple),
('namedtuple', bench_namedtuple),
('typing.NamedTuple', bench_typing_namedtuple),
('dataclass', bench_dataclass),
('dataclass(slots)', bench_dataclass_slots)
]
results = []
for name, func in benchmarks:
start = time.perf_counter()
func()
duration = time.perf_counter() - start
results.append((name, duration))
for name, duration in results:
print(f"{name:20s}: {duration:.4f} seconds")