乐趣区

关于后端:elixir-0073-beam-内置的内存数据库-ETS

在 beam 虚拟机里,过程之间个别通过消息传递来沟通,而消息传递是须要复制而非共享的。在音讯体积小,且只在大量的过程之间流传时,是没有什么性能问题的。而如果咱们须要在大量过程之间共享大量的数据,那么消息传递就显得非常低效且没有必要了。

Erlang 很早就思考到了这个场景,在 beam 中增加了 ETS(erlang term storage),它能够让不同过程间接共享数据。让咱们来试试看它是如何应用的:

首先咱们新建一个 ETS 表,抉择命名为 :table_a,类型采纳 set,相似与哈希表。

:ets.new(:table_a, [:named_table, :set])

咱们能够用 :ets.info/1 函数来查看这个表的详细信息。

iex(2)> :ets.info :table_a
[
  id: #Reference<0.679153060.3873570820.49251>,
  read_concurrency: false,
  write_concurrency: false,
  compressed: false,
  memory: 307,
  owner: #PID<0.239.0>,
  heir: :none,
  name: :table_a,
  size: 0,
  node: :nonode@nohost,
  named_table: true,
  type: :set,
  keypos: 1,
  protection: :protected
]

留神到这里和 socket 一样,都需有一个过程作为 owner,以绑定 erlang 过程世界与外界(ets,port 等)的关系,从而使 link 和 mointor 机制能够延展到这些外界部件上来。一旦 owner crash,ets 表也会随之隐没。

“:set” 类型的应用形式和 map 差不多。默认的 key 是 tuple 的第 1 个元素(从 1 开始计数)。

让咱们持续应用 BonyTrace 来测试一下,看看是不是真的不须要任何消息传递就能够共享数据。

    spawn(fn ->
      BonyTrace.start(self())

      table = :ets.new(:ets_map, [:named_table, :set, :public])

      :ets.insert(table, {"key1", "value1"})

      spawn(fn ->
        [{"key1", "value1"}] = :ets.lookup(table, "key1")
      end)

      :timer.sleep(5000)
    end)

留神 ets table 必须要设置为 :public 才能够让其它过程拜访。执行结束看到只打印出了计时器 timeout 的音讯。所以 ets 的确是很不便的过程间数据共享工具。

#PID<0.331.0> RECEIVED                                 +0.000000s
MESSAGE: :timeout
退出移动版