「CPythonのソースコードを読んでみた」を読んで
背景
を読んで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
bytesobject は methane さんによって tp_dealloc が必要なくなっていて、listobject は tp_dealloc の際に要素をすべて走査して deref している分重いというのが速度差の原因ではないか。