erlang ets中safe_fixtable的用法分析

該方法主要使用在通過迭代的方式下遍歷整個的ets數據

  • 如使用ets:next()或者ets:match_object方法或者ets:select方法迭代的遍歷整個ets數據

作用

  • 如果出現數據的刪除,可以平滑的處理這些迭代器的使用,不至於因爲刪除而導致的迭代報錯
  • 即使設置了ets:safe_fixtable(Tab, true)也是可以在另外一個進程刪除數據,並且刪除也是有效的
  • 注意一旦設置了之後也要設置回ets:safe_fixtable(Tab, false)

erlang網站信息翻譯

  • 刪除一個正在fixed的ets對象,他是不是立刻釋放內存的,直到進程釋放了這個fix。並且如果加了fix操作,則table的性能會明顯的變慢。
  • 可以使用info(Tab, safe_fixed_monotonic_time)來展示進程fix的table信息。如果多個進程都在fix table則需要報警,或者fix table過長時間,也需要報警。
  • 對於ordered_set類型的ets,以及一次性全部讀取的數據,則沒有必要加載fix table
  • 一個進程fixtable,則這個table會一直fix,直到進程主動的釋放或者進程關閉。

測試點

  • 不添加safe_fixtable,在迭代ets時,添加ets數據,有時會展示在迭代中,有些事不能展示在迭代中
  • 不添加safe_fixtable,在迭代ets時,刪除ets數據,回導致迭代報錯
  • 不添加safe_fixtable,在迭代ets時,修改ets的原有數據,可以展示最新的數據
  • 添加safe_fixtable時,在迭代ets時,添加ets數據,有時會展示在迭代中,有些是不能展示在迭代中
  • 添加safe_fixtable時,在迭代ets時,刪除ets數據,可以正常迭代完成,迭代中不會包含刪除的信息
  • 添加safe_fixtable時,在迭代ets時,修改ets的原有數據,可以展示最新的數據

不加safe_fix的報錯信息

測試代碼

%% 當前的代碼註釋了safe_fixtable,則會出現迭代調用報錯
%% 放開safe_fixtable之後,則迭代正常,跳過了刪除的數據信息,可以正常的執行完迭代,'$end_of_table'返回
-record(map, {
    id = 0,             %% 地圖編號id,每個副本唯一
    map_id = 0,         %% 基礎地形圖id
    map_cell = []      %% 地圖標記 [#map_cell{}]
}).
test_ets_fix_up() ->

    ets:delete(ets_fix_up),

    ets:new(ets_fix_up, [{keypos, #map.id},named_table, public, set]),

    ets:insert(ets_fix_up,
        [#map{id = 1, map_id = 1111,map_cell = [111111]},
        #map{id = 2, map_id = 222,map_cell = [111111]},
        #map{id = 3, map_id = 333,map_cell = [111111]},
        #map{id = 4, map_id = 4444,map_cell = [111111]}]
    ),

    spawn(
        fun() ->
%%            ets:safe_fixtable(ets_fix_up, true),
            Key = ets:first(ets_fix_up),

            io:format("111111 key  = ~p ~n", [Key]),
            timer:sleep(3000),
            Key1 = ets:next(ets_fix_up, Key),
            io:format("22222 key1  = ~p ~n", [Key1]),
            timer:sleep(3000),

            Key2 = ets:next(ets_fix_up, Key1),
            io:format("333333 key2  = ~p ~n", [Key2]),
            timer:sleep(3000),

            Key3 = ets:next(ets_fix_up, Key2),
            io:format("444444 key3  = ~p ~n", [Key3]),
            timer:sleep(3000),

            Key4 = ets:next(ets_fix_up, Key3),
            io:format("555555 key4  = ~p ~n", [Key4]),
            timer:sleep(3000)

%%            ets:safe_fixtable(ets_fix_up, false)
        end),


    spawn(
        fun() ->
            timer:sleep(2000),
%%            ets:delete(ets_fix_up,2),

            ets:insert(ets_fix_up, #map{id = 2, map_id = 1111,map_cell = [111111]}),
            ets:insert(ets_fix_up, #map{id = 3, map_id = 1111,map_cell = [111111]}),

            io:format("spawn2 = del= ~p ~n", [2]),
%%            ets:delete(ets_fix_up,3),
            io:format("spawn2 6s del = ~p ~n", [3])

        end),

    ok.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章