프로그래밍/Python

[Python] 이진 파일로부터 int array 읽어 들이는 3가지 방법 성능 비교

채윤아빠 2021. 4. 29. 22:30
728x90
반응형

앞 글에 이어서 "이진 파일로부터 int array 읽어 들이는 3가지 방법들"간의 성능을 비교해 보도록 하겠습니다.

세 방법간 성능 비교를 위하여 아래와 같은 코드를 작성하였습니다.

"cam-20220503_1255.mp4.idx"에는 int32 정수값이 18,001여개가 들어 있는 이진파일입니다.

# comparision load int array

import timeit

setup = """
import numpy as np
import os
import struct

# index has 18000 int32
video_file_name = 'cam-20220503_1255.mp4'

video_index_file = open(f'{video_file_name}.idx', 'rb')
video_index_file.seek(0, os.SEEK_END)
file_size = video_index_file.tell()
total_frame_count = int(file_size / 4)
"""

result1 = timeit.timeit("""
video_index_file.seek(0, 0)

frame_index_list = list()
frame_count = 0
for index in range(total_frame_count):
    frame_index_bytes = video_index_file.read(4)
    if (frame_index_bytes == None):
        break
    (frame_index, ) = struct.unpack('=i', frame_index_bytes)
    frame_index_list.append(frame_index)
    frame_count += 1
""", setup = setup, number = 3000)


result2 = timeit.timeit("""
video_index_file.seek(0, 0)
data_bytes = video_index_file.read()
frame_list = struct.unpack(f'={total_frame_count}i', data_bytes)
""", setup = setup, number = 3000)


result3 = timeit.timeit("""
video_index_file.seek(0, 0)
data_bytes = video_index_file.read()
frame_list = np.frombuffer(data_bytes, np.int32)
""", setup = setup, number = 3000)

print(f'result1 = {result1}')
print(f'result2 = {result2}')
print(f'result3 = {result3}')

위와 같은 성능비교 예제를 실행한 결과는 다음과 같습니다.

result1 = 11.304136499999998
result2 = 0.5849311000000004
result3 = 0.05164079999999949

당연하게도 첫 번째 방법은 매번 리스트 마지막에 새로 읽어들인 int 값을 추가하기 때문에 가장 성능이 좋지 않습니다.

두 번째 방법은 동일하게 struct.unpack() 함수를 이용하지만, 개수를 지정하여 반환받는 방법인데, 첫 번째 방법보다는 월등하게 빠릅니다.

마지막 세 번째 방법은 numpy.frombuffer() 함수를 이용하는 방법인데, 가장 빠릅니다. 아무래도 배열을 다루는데 최적화된 패키지다보니 최적의 성능을 보여줍니다. 배열 관련해서는 당연하게도 numpy를 애용해야할 것 같습니다.

참고자료