なぜメモリ管理が必要なのか
スマートフォンのようなデバイスでは、利用可能なメモリが限られています。そのため、使用されていないメモリを適切に解放しないと、徐々にメモリ不足となり、システムが重くなったりクラッシュしたりといった問題が発生します。
そういった問題が起こらないよう、開発者には、不要になったメモリを解放してアプリのパフォーマンスを維持・向上させることが求められます。
CやC++のような言語では、開発者自身がfree
などを使ってメモリを明示的に解放する必要がありますが、これは非常に手間がかかります。
そこで、iOS(SwiftやObjective-C)では、ARC(Automatic Reference Counting)という仕組みを用いてメモリ管理を自動化し、開発者の負担を軽減しています。
ARC (Automatic Reference Counting) とは?
- オブジェクトの参照数(Reference Count)を数え、不要になったタイミングで自動的にメモリを解放する仕組み。
- 誰からも参照されなくなったオブジェクトは、自動的にメモリから解放される。
ARCはSwiftが自動で行うメモリ管理方法です。ARCはスコープ内にあるオブジェクトの参照数を動的にカウントし、参照されると+1、解放されると-1とカウントが変化します。
class Dog {}
func example() {
let dog = Dog() // ここで参照カウント = 1
// dog がスコープを抜けたら = 参照カウント 0 -> 解放される
}
そもそも、なぜ参照を数えるのか?
使われなくなったメモリは、できるだけ早く解放するのが理想です。その「解放すべきタイミング」を判断するために、Reference Counting(参照カウント)が使われます。
以下の例を見てみましょう:
class Cat {}
var a: Cat? = Cat() // 参照カウント = 1(aが参照)
var b = a // 参照カウント = 2(aとbが参照)
a = nil // 参照カウント = 1(bだけが参照)
b = nil // 参照カウント = 0 → 解放!
この例では、最後の行b= nil
で参照カウントが0にな理、誰からも参照されていないと判断されてから、安全にメモリが解放されています。
実際のアプリではもっと複雑なオブジェクト同士の関係があるため、メモリを解放できるタイミングが明示的というのはARCを使う大きなメリットです。
ガベージコレクション(GC)との違い
JavaやJavaScriptなどの言語では、ガベージコレクション(GC)というメモリ管理手法が使われています。これは、一定のタイミングでメモリ全体をスキャンし、「使われていなさそうなオブジェクト」をまとめて解放する仕組みです。
しかし、GCには以下のようなデメリットがあります:
- メモリスキャンが重く、パフォーマンスに影響を与える
- 解放のタイミングが不確定で、リアルタイム性が低い
このような理由から、特にiOSのようにリソースが限られた環境では、GCよりもARCのほうがパフォーマンスに優れているとされています。
ARCのデメリット:Retain Cycle (循環参照)
しかし、何事にも完璧なものはなく、もちろんARCにも欠点があります。それがRetain Cycle(循環参照)です。Retain Cycleが発生すると、参照カウントが0にならずメモリが解放されないという問題が起こります。いわゆるメモリリークが発生し、これはアプリのクラッシュやパフォーマンスの低下を引き起こす原因となります。
この問題とその対処法(weak や unowned の使い方など)については、別の記事で詳しく解説する予定です。
まとめ
- スマートフォンのようなメモリに制限がある環境では、効率的なメモリ管理が必要不可欠。
- Swiftでは、ARC(Automatic Reference Counting) によって、オブジェクトの参照数を自動で管理し、使われなくなったメモリを自動で解放してくれる。
- ARCでは、オブジェクトが誰からも参照されなくなったタイミングで解放されるため、明確なメモリ管理が可能。
- JavaやJavaScriptのようなGC(ガベージコレクション)に比べて、リアルタイム性やパフォーマンス面でARCは有利。
- ただし、ARCにも弱点があり、Retain Cycle(循環参照)によってメモリが解放されないことがあるため注意が必要。
参考