0Pricing
Lua Academy · レッスン

メモリリークの回避

Luaでよくあるリークパターンと、それを防ぐための戦略を学びます。

「メモリリークの回避」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

Luaにおけるメモリリークとは

メモリリークとは、プログラムが不要になった後も参照によってGCの回収が妨げられ、オブジェクトがメモリ内に蓄積されることです。

よくあるリーク:グローバルへの蓄積

オブジェクトをグローバルテーブルに保存したまま削除しないのは、典型的なリークです。グローバルテーブルは常にGCルートです。

local cache = {}  -- global-like upvalue
function storeResult(key, val)
  cache[key] = val  -- never evicted!
end

修正:サイズ制限付きキャッシュ

キャッシュサイズに上限を設け、LRU方式または単純なサイズ上限によって古いエントリを追い出してください。

local MAX = 100
local function boundedStore(cache, key, val)
  if #cache >= MAX then
    table.remove(cache, 1)  -- evict oldest
  end
  cache[key] = val
end

よくあるリーク:イベントリスナー

クロージャをイベントリスナーとして登録したまま登録解除しないと、そのクロージャとupvalueの両方が存続し続けます。

local listeners = {}
function on(event, fn)
  listeners[event] = listeners[event] or {}
  listeners[event][#listeners[event]+1] = fn
end
-- Always provide off() to deregister!

修正:弱リスナーテーブル

リスナーを弱い値のテーブルに保存すると、購読者オブジェクトが回収されたときに、そのリスナーも自動的に削除されます。

local listeners = setmetatable({}, {__mode = "v"})

よくあるリーク:大きなテーブルを捕捉するクロージャ

大きなテーブルを捕捉するクロージャは、テーブルの一部しか必要でない場合でも、クロージャが存続する限りそのテーブルを保持します。

local bigData = {-- 100MB of data --}
local fn = function()
  return bigData[1]  -- bigData stays alive!
end

修正:必要な値を取り出す

クロージャを作成する前に必要な値だけを取り出し、大きなテーブルを回収できるようにしてください。

local needed = bigData[1]
bigData = nil  -- allow collection
local fn = function() return needed end

コルーチンによるリーク

中断中のコルーチンは存続しており、すべてのローカル変数を保持します。終了したコルーチン(ステータスが"dead"のもの)は回収できます。中断中のコルーチンを追跡不能にしないでください。

文字列の蓄積

ループ内で..を使って文字列を連結すると、多数の中間文字列が作成されます。大きな文字列を効率的に構築するには、table.concatを使用してください。

local parts = {}
for i = 1, 1000 do parts[i] = tostring(i) end
local result = table.concat(parts, ",")

リークのデバッグ

操作の前後でcollectgarbage("count")を使用し、メモリの増加量を測定してください。不審な増加をログに記録して、リークの発生源を絞り込みます。

local before = collectgarbage("count")
-- ... run operation ...
collectgarbage()
local after = collectgarbage("count")
print(("Delta: %.1f KB"):format(after - before))

プロファイリングツール

luamemprofのようなツールや、独自のdebug.sethookによる割り当てカウンターを使うと、最も多くのメモリを割り当てているコードパスを追跡できます。

メモリリークに関する質問

最もメモリリークを引き起こしやすいパターンはどれですか?

復習:メモリリークの回避

Luaのリークは、上限のないキャッシュ、登録解除されていないリスナー、大きなテーブルを参照するクロージャ、放置された中断中のコルーチンによって発生します。弱テーブルとサイズ制限付きキャッシュを使用し、collectgarbage("count")でリークを検出・防止してください。

よくある質問

「メモリリークの回避」レッスンは無料ですか?

はい。「メモリリークの回避」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「メモリリークの回避」で何を学びますか?

Luaでよくあるリークパターンと、それを防ぐための戦略を学びます。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「メモリリークの回避」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Luaガベージコレクターの基礎
  2. 弱いキーと弱い値
  3. __gcによるファイナライザー
  4. メモリリークの回避
← Lua Academyに戻る