LoginSignup
2
2

More than 3 years have passed since last update.

PyCall.rb でメモリリークみたいな現象が起こったので workaround

Last updated at Posted at 2020-03-02

まさかのメモリリーク?

もはやぼくにとって手放せなくなったmrknさんのPyCall.rbですが、メモリリーク的な現象に遭遇して困ったので逃げ道も含めて情報共有しておきます。

検証コード 

まずこちらは何の問題もない Python コードです。ふつうに動き、問題は起きません。

import cv2
for i in range(1000):
  img = cv2.imread("foo.jpg")
  print(img.shape)

これを PyCall を使って Ruby で書きます。

require "pycall"
cv2 = PyCall.import_module("cv2")
1000 times do
  img = cv2.imread("foo.jpg")
  puts img.shape
end

するとどうでしょう。なんとメモリがどんどん消費されていくではありませんか!どうもPyCall内で使われたメモリは参照が残るのかGCが処理してくれないようです。img = nil とか cv2 = nil とかしても無駄でした。

workaround

で結局どうしたかと言うと格好悪いですがプロセス切り離しました。多少パフォーマンス落ちますが、さすがにここまでやれば大丈夫なようです。

require "pycall"
def quarantine
  cv2 = PyCall.import_module("cv2")
  img = cv2.imread("foo.jpg")
  puts img.shape
end

1000.times do
  Process.waitpid(
    fork {
      quarantine
    }
  )
end

誰かもっとスマートなやり方見つけたら教えてください。

2
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2