メモリ周りについて
rustのウリの1つとしてはメモリ安全が挙げられる。
ただ、phpのようなgcが勝手に動く言語をやってきた自分にはどういうことが
ありがたいのかが具体的にわからない。
rustにはGCがないけどメモリ安全 ← ?
という疑問があったので、メモリ周りの知識とか
GCについて勉強してみた
ヒープメモリ
まずは、動的メモリ割り当て
不要になれば、割り当てられたメモリを解放すること
何のために必要なの?
例えば、膨大なデータが入るからといって
データを格納する配列を10万個用意しても
ムダになる可能性がある。
実行時に効率よく割り当てておきたい。
そのために用意されているのがヒープ領域
プログラムが自由に読み書きできる領域のこと
(動的メモリ管理で使用されるメモリ空間)
通常はプログラムが終了すればヒープ領域は解放される
何らかの原因で、アプリケーションが獲得したメモリが解放されず
メモリが空間に残ってしまうことがある
これがメモリリーク
と呼ばれるもの
ヒープ領域は ~New領域~ と ~Old領域~ に分けられて使われる
- New領域には生成されたあとすぐ廃棄される(寿命の短い?)オブジェクトが入る。
- Old領域にはそうでない寿命の長いオブジェクトが入る
GCについて
GCについての理解は、メモリを使いすぎないようにするものくらいにしか知らなかった。
実は大きく分けて2つあるらしい
- Scavenge GC
New領域を対象としたメモリのクリーンを行う
すぐ廃棄されるオブジェクトを対象にするので動きは早い
→ 動く頻度が多く、多くのオブジェクトを対象にしないことが多いため
- Full GC
Old領域を含む全領域に対してのメモリクリーン
Scavenge GCよりかは実行に時間がかかる
GCを意識したプログラミング
メモリに優しいプログラムを書くには、オブジェクトの寿命を延ばさない
寿命の長いオブジェクトが多くあると、Old領域に割り当てられるものが増え
Full GCに時間がかかる
phpのGC については下記スライドが大変参考になりました
PHP の GC の話
5.3以前では参照カウント方式における循環参照が解決できなかったのは
初めて知りました。。
unset($value)
の必要性。。
GCということで最近見たgolangについてのものも面白かったです
Go言語のリアルタイムGC 理論と実践 | プログラミング | POSTD
GCが、レイテンシ / スループットのどちらに最適化を行うのか、
自分が作るアプリケーションはどちらが適切なのか
1つ判断軸が増えるなぁと。けどこういうのって、既存のものに何かしら
限界が近づいて考慮されるものなんだろうな。。
だって、言語レベルで変えなきゃいけないって相当ですよね、、
スタティック領域
プログラムの開始から終了までメモリ割り当てが変化しない部分
スタック領域
メモリ上のローカル変数やメソッドの情報を格納する領域のこと
ジェネリクス
静的型付け言語において冗長なコードを書かなくて済むような仕組み
関数で、複数の型に対応した引数書きたいとか
struct Point<T> {
x: T,
y: T,
}
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
fn test<T>(x: T) {
x + 1
}
let f = test;
let x = test(1);
println!("x is: {}", x);
所感
普段気にすることのない低レイヤー、ハードウェア側のことを
勉強するいい機会になった
とりあえず何か作ろう、何か。