薄いブログ

技術の雑多なことを書く場所

「CPythonのソースコードを読んでみた」を読んで

背景

inside.estie.co.jp

を読んでExステージについて検証したくなったので

alloc_bytes と alloc_list の速度差について

def alloc_bytes(size):
  return b"ABCDEFGH" * size

while True:
  alloc_bytes(1024**2 * 128)
def alloc_list(size):
  return [0, 1] * size

while True:
  alloc_list(1024**2 * 64)

の2つを大体時間実行して Instruments の Time Profiler を用いて観察した。

$ python3 bytes.py

Weight     Self    Weight    Symbol Name
 21.13 s  100.0%        0 s     python3.11 (51417)
 21.13 s  100.0%        0 s      start
 21.13 s  100.0%        0 s       Py_BytesMain
 21.13 s  100.0%        0 s        pymain_main
 21.13 s  100.0%        0 s         Py_RunMain
 21.13 s  100.0%        0 s          _PyRun_AnyFileObject
 21.13 s  100.0%        0 s           _PyRun_SimpleFileObject
 21.13 s  100.0%        0 s            PyEval_EvalCode
 21.13 s  100.0%        0 s             _PyEval_EvalFrameDefault
 21.09 s   99.8%        0 s              bytes_repeat
 21.09 s   99.8%    21.09 s               _platform_memmove$VARIANT$Haswell
38.00 ms    0.1%    1.00 ms              _PyObject_Free

$ python3 list.py

Weight    Self   Weight  Symbol Name
20.93 s  100.0%     0 s     python3.11 (51455)
20.93 s  100.0%     0 s      start
20.93 s  100.0%     0 s       Py_BytesMain
20.93 s  100.0%     0 s        pymain_main
20.93 s  100.0%     0 s         Py_RunMain
20.93 s  100.0%     0 s          _PyRun_AnyFileObject
20.93 s  100.0%     0 s           _PyRun_SimpleFileObject
20.93 s  100.0%     0 s            PyEval_EvalCode
20.93 s  100.0%     0 s             _PyEval_EvalFrameDefault
14.84 s   70.8% 14.84 s              list_repeat
 6.09 s   29.1%  6.06 s              list_dealloc

github.com

github.com

bytesobject は methane さんによって tp_dealloc が必要なくなっていて、listobject は tp_dealloc の際に要素をすべて走査して deref している分重いというのが速度差の原因ではないか。