PythonにおけるLazy Loading(遅延読み込み)のトライ
Pythonでデータ処理や画像処理を行う際、「Lazy Loading(遅延読み込み)」という手法を使うと、効率的にメモリを管理し、大規模なデータ処理を快適に行えるようになります。本記事では、Lazy Loadingの概要と、一括読み込みとの違いを実際のテスト結果をもとに解説します。
🔹 Lazy Loadingとは?
Lazy Loading(遅延読み込み)とは、必要になるまでデータをメモリに読み込まない処理方式です。すべてのデータを一度にメモリ上に展開する「一括読み込み」とは対照的で、メモリ効率が良く、大規模データや大量の画像ファイルを扱う際に有効な手法です。
🔹 一括読み込みとの違い
- 一括読み込み: 全データを一度にメモリ上に読み込み、処理を開始します。メモリ使用量が非常に多くなり、大量のデータを扱うとメモリ不足になる可能性があります。
- Lazy Loading: 必要なデータを逐次的に読み込むため、メモリの消費を抑えられます。メモリ使用量が少なく、大量のデータ処理にも対応できます。
🔹 PythonによるLazy Loadingの実例
画像を用いたサンプルコードでLazy Loadingと一括読み込みの違いを検証します。
サンプルコード
import os
import tempfile
from PIL import Image
from memory_profiler import profile
def create_mock_images(num_images, image_size=(100, 100), directory=None):
if directory is None:
directory = tempfile.mkdtemp()
image_paths = []
for i in range(num_images):
img = Image.new("RGB", image_size, color=(i % 256, (i * 2) % 256, (i * 3) % 256))
path = os.path.join(directory, f"mock_{i}.jpg")
img.save(path, "JPEG")
image_paths.append(path)
return image_paths
def load_images_lazy(image_paths):
for path in image_paths:
with Image.open(path) as img:
img.load()
yield img.copy()
def load_images_all(image_paths):
images = []
for path in image_paths:
with Image.open(path) as img:
img.load()
images.append(img.copy())
return images
@profile
def process_images_lazy(image_paths):
for img in load_images_lazy(image_paths):
_ = img.size
@profile
def process_images_all(image_paths):
images = load_images_all(image_paths)
for img in images:
_ = img.size
if __name__ == "__main__":
num_images = 100000
image_paths = create_mock_images(num_images)
print(f"Mock images created in directory: {os.path.dirname(image_paths[0])}")
print("Processing images with lazy loading:")
process_images_lazy(image_paths)
print("Processing images with all-at-once loading:")
process_images_all(image_paths)
🔹 実行結果(メモリ使用量比較)
Lazy Loadingの場合
Line # Mem usage Increment Occurrences Line Contents
=============================================================
36 53.4 MiB 53.4 MiB 1 @profile
39 53.6 MiB 0.2 MiB 101 for img in load_images_lazy(image_paths):
41 53.6 MiB 0.0 MiB 100 _ = img.size
一括読み込みの場合
Line # Mem usage Increment Occurrences Line Contents
=============================================================
43 53.6 MiB 53.6 MiB 1 @profile
46 57.5 MiB 3.9 MiB 1 images = load_images_all(image_paths)
47 57.5 MiB 0.0 MiB 101 for img in images:
48 57.5 MiB 0.0 MiB 100 _ = img.size
🔹 Lazy Loadingのすごさまとめ
Lazy Loadingを使用すると、
- 一度にメモリを大量に消費することなく、安定した処理が可能になる。
- 特に画像や大規模データを大量に扱う際、メモリ不足を避けられる。
- スケーラブルで効率的な処理が可能になる。
大規模データ処理を行う際はLazy Loadingの活用を検討すると、効率的で安定したアプリケーションを構築できます。