hchunhui / librime-lua

Extending RIME with Lua scripts
BSD 3-Clause "New" or "Revised" License
310 stars 43 forks source link

Opencc有 memory leak issue, #147 #200 #206

Open shewer opened 2 years ago

shewer commented 2 years ago

只要 產生實例後 memory 就會長大 Opencc('t2s.json')
擇一暫時停用 opencc

-- rime.lua
Opencc= nil  -- 禁用 opencc 
-- bypass 
Opencc= function(fn)
    return  {
       convert= function(self,text) return text end,
       convert_text = function(self,text) return text end,
       convert_word= function(self,text) return end,
       random_convert_text = function(self,text) return text end,
    }
end
oniondelta commented 1 year ago

最新版 librime-lua 還會 memory leak 嗎? 如果尚有,新版 librime-lua 會修改為不 leak 嗎? 另寫法上有什麼要注意的嗎?

用了一陣子,發現 memory 上上下下的,但好似真的會緩步上升?! 原本30MB上下起伏,後來到近50MB上下起伏,目前還在觀察研究中, 是否為 opencc 造成 memory leak 現象? 如果是,有什麼寫法可以避免 memory leak? 或是以下代碼有否改進之處?


以下精簡寫法,實作增加兩個開關去控制兩種 comment 的分別顯示 之前新增一個方案用 ReverseDb 提取 bin 去實現第二個 comment 附加,但太繞, 改用 Opencc 附加 comment(b_mark)

local function opencc_comment_filter(input, env)
    local opencc = Opencc("back_mark.json")
    for cand in input:iter() do
        local b_mark = opencc:convert_word(cand.text) or {''}
        cand:get_genuine().comment = cand.comment .. b_mark[1]
        yield(cand)
    end
end
shewer commented 1 year ago

最新版 librime-lua 還會 memory leak 嗎? 如果尚有,新版 librime-lua 會修改為不 leak 嗎? 另寫法上有什麼要注意的嗎?

目前沒有找到改善方案,可以用 Component.Filter 把 simplifier 包到 lua_filter中,但是 simplifier 把 candidate 再包一層 ShadowCandidate 如果再加上 其他 simplifier 又會再包上一層 Shadow(Shadow(cand)),會影響 Phrase (字典) 詞頻 不能更新

爲了避免 再打被 t2s s2t .... 繁簡轉換 ,此模組放在 此類之前,取得 ShadowCandidate 再用 get_genuine取出原來的cand.

<name_space>:
    option_name: <name_space>
    opencc_config: 
    tips: all
    show_in_comment: true
    tags: 
--  使用 config 設定 simplfier 參數
local init_config(env,path)  
  local config=env.engine.schema.config
  path= path or env.name_space
  config:set_string(path .. "/option_name" , env.name_space)
  config:set_string(path .. "/opencc_config", "")
  config:set_string(path .. "/tips", "all")
  config:set_bool(path .. "/show_in_comment", true)
end
local F={}
function F.init(env)
   init_config(env)
   env.engine.context:set_option(env.name_space, true) -- 啓動此filter
   env.simp= Component.Filter(env.engine, "", "simplifier@" .. env.name_space)
end
function F.fini(env)
end
function F.tags_match(seg, env)
  return env.simp:tags_match(seg,env)
end
function F.func(inp,env,cands)
  local tran= env.simp(inp,cands)
  for scand in tran:iter() do
    local cand_type= cand:get_dymaic_type()
    if cand_type == "Shadow" then
        scomment= scand.comment
        local cand= scand:get_genuine() 
        yield(cand)
    else 
         yield(scand)
    end
end
ksqsf commented 12 months ago

最近碰到类似内存泄露问题,手动使用 collectgarbage() 可以强行回收内存。

怀疑原因是 https://stackoverflow.com/questions/43150742/is-there-any-way-to-let-lua-garbage-collector-know-about-memory-requirements-of 里提到的,Lua 侧不知道 C++ 侧内存对象大小,低估了释放的内存,所以 GC 次数太少。