先日、速度改善のためRailsコードをGoで書き直して、FFIを使ってみた という記事を書いたのですが、
このコードがメモリリークを起こしてしまいました。。
golang初心者のため、C.Cstringがgoのメモリ解放の管理から外れているいうことを把握していませんでした。。
return C.CString(string(resultJSON))
となっているとこを deferで解放するようにしました。
ret := C.CString(string(resultJSON))
defer C.free(unsafe.Pointer(ret))
return ret
メモリリークしないか1時間くらい動かしてチェック
end_time = (Time.now + 60 * 60).to_i
while (Time.now.to_i < end_time)
# ObjectSpaceはデフォルトがバイト表示
# psのrssはデフォルトがキロバイト表示
# Process.pidはカレントプロセスのプロセスID
puts "[BEFORE] memsize_of_all: #{(ObjectSpace.memsize_of_all * 0.001 * 0.001).round(2)} MB, rss: #{(`ps -o rss= -p #{Process.pid}`.to_i * 0.001).round(2)} MB"
Ffi::Sample.sampleCalc({:test=>"test"}.to_json)
puts "[AFTER] memsize_of_all: #{(ObjectSpace.memsize_of_all * 0.001 * 0.001).round(2)} MB, rss: #{(`ps -o rss= -p #{Process.pid}`.to_i * 0.001).round(2)} MB"
end
メモリが増えてないのでOK!
[BEFORE] memsize_of_all: 56.8 MB, rss: 173.32 MB
[AFTER] memsize_of_all: 57.76 MB, rss: 173.59 MB
[BEFORE] memsize_of_all: 57.76 MB, rss: 173.59 MB
[AFTER] memsize_of_all: 58.72 MB, rss: 173.59 MB
:
:
[BEFORE] memsize_of_all: 53.9 MB, rss: 173.36 MB
[AFTER] memsize_of_all: 54.87 MB, rss: 173.36 MB
[BEFORE] memsize_of_all: 54.87 MB, rss: 173.36 MB
[AFTER] memsize_of_all: 55.83 MB, rss: 173.36 MB
ちなみに修正前は、下記のように大変な結果になっていました。。
[BEFORE] memsize_of_all: 53.04 MB, rss: 156.92 MB
[AFTER] memsize_of_all: 42.35 MB, rss: 161.63 MB
[BEFORE] memsize_of_all: 42.36 MB, rss: 161.63 MB
[AFTER] memsize_of_all: 43.32 MB, rss: 161.64 MB
:
:
[BEFORE] memsize_of_all: 37.1 MB, rss: 2116.28 MB
[AFTER] memsize_of_all: 38.06 MB, rss: 2116.28 MB
[BEFORE] memsize_of_all: 38.06 MB, rss: 2116.28 MB
[AFTER] memsize_of_all: 39.02 MB, rss: 2115.34 MB
メモリリークしてないか、気になる場合はチェックした方がいいですね