2

最近、DjangoプロジェクトとWebFactionのメモリ使用量に問題が発生しました。

webfactionでこのプロジェクトのメモリ内で実行されている2つのプロセスは次のとおりです。

30396  4-20:20:00 13486 
30404  4-20:20:00 13487 

ビューが実行された後、プロセスの1つが大幅に増加します。

69720  4-20:20:22 13486 
30404  4-20:20:22 13487 

ご覧のとおり、最初のプロセスではメモリ使用量が2倍以上になりました。この関数は頻繁に使用されるため、何が起こっているのかを把握する必要があります。次のビューに絞り込んだと思います(画像のアップロード、詳細の追加、サムネイルのトリミングは3ステップのプロセスです)。

これが下のビューです。写真オブジェクトを取得し、ファイルから画像をロードし、ユーザーが送信したボックス座標を取得して、200,200サイズの画像を作成します。この新しく作成された画像は、ファイル名に.thumbnailを付けてディスクに書き戻され、写真オブジェクトが保存されます。

@login_required
def upload3(request, photo_pk):
    photo = get_object_or_404(Photo, pk=photo_pk, user=request.user)
    if request.method == "POST":
        form = upload3Form(request.POST)
        if form.is_valid():
            im = Image.open(photo.image.path)
            try:
                box =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2'])
            except:
                box = ('0','0','1000','1000')
            cropped = im.crop(box)
            cropped.thumbnail((200,200),Image.ANTIALIAS)
            result = os.path.splitext(photo.image.path)
            cropped.save(result[0] + '.thumbnail' + result[1])
            photo.status = 3
            photo.save()

私が間違っているかもしれないことについてのどんな考えでも大いに感謝されるでしょう。

Update 1:テストに使用される画像はすべてJpegで、サイズは約3600 x 2700で、画像あたり約2MBです。

4

2 に答える 2

2

2Mの数値は圧縮されたJPEG画像用ですが、圧縮されていない場合、3600 x 2700のトゥルーカラーは約38M(4B /ピクセルで9,720,000ピクセル)になり、発生しているメモリ使用量の増加に近くなります。

これはPILの既知の問題です。40000x40000ピクセルの黒い画像をpngとして送信することで、ピクセル爆弾を作成できます。ロードする前に必ず解像度を確認してください(または、OutOfMemoryを処理するtry /exceptブロックでコードを保護してください)。im.tile属性を使用して画像をチャンクごとに処理すると、メモリフットプリントが低くなるかどうかを確認してください。

チェックする価値があるかもしれません:

より大きな画像を処理するときにメモリをより適切に処理すると言われているいくつかの選択肢:

  • GDAL(地理空間データ抽象化ライブラリ)
  • OIIO(OpenImageIO)
  • マホタス(NumPy)

[ アップデート ]

PILにオブジェクトをメモリから解放する方法があるかどうか知っていますか?理論的には、このビューが同じように機能する必要があるため、このビューに最適ですが、画像をより適切に処理するためです。

  • メモリの急増を回避するために、im.tile代わりにを使用して巨大な画像を検出し、それらをチャンクで処理しようとすることができますim.crop(残念ながら、より低いレベルで動作します)。
  • スパイクを短くするために、中間イメージオブジェクトをできるだけ早く削除できます(gcモジュールを使用すると、ガベージコレクターに強制的にクリーンアップさせることができます)。
于 2012-03-06T08:42:02.273 に答える
0

たくさんの掘り下げと行き止まりの後、私はどこにも提案されていない何かを試しました、そしてそれはうまくいきました。

PILで使用される画像オブジェクトを含む各オブジェクトで、使い終わったらオブジェクトを削除する必要がありました。したがって、たとえば:

im = Image.open(photo.image.path)
try:
    box  =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2'])
except:
    box = ('0','0','1000','1000')
cropped = im.crop(box)
newimage = cropped.resize((form.cleaned_data['dw'],form.cleaned_data['dh']),Image.ANTIALIAS)
del im
del cropped 

したがって、オブジェクトの処理が完了したら、そのアイテムに対してdelを呼び出します。問題は解決したようです。私はもはや記憶力の増加がなく、これ以上幸せになることはできませんでした。

于 2012-03-15T15:25:29.437 に答える