查看源代码 counters (erts v15.2)
计数器函数
此模块提供了一组函数,用于对共享的可变计数器变量进行操作。该实现不使用任何软件级别的锁定,这使得它在并发访问时非常高效。计数器被组织成具有以下语义的数组:
- 计数器是 64 位有符号整数。
- 计数器在溢出和下溢操作时会回绕。
- 计数器初始化为零。
- 写入操作保证原子性。从单个写入操作中看不到任何中间结果。
- 可以使用选项
atomics
或write_concurrency
创建两种类型的计数器数组。atomics
计数器具有良好的整体性能和一致的语义,而write_concurrency
计数器则以潜在的读取不一致为代价,提供更好的并发写入性能。请参见new/2
。 - 计数器数组的索引是从 1 开始的。大小为 N 的计数器数组包含 N 个计数器,索引从 1 到 N。
概要
函数
将 Incr
加到索引为 Ix
的计数器上。
读取计数器值。
以映射的形式返回有关计数器数组的信息。
创建一个新的包含 Size
个计数器的计数器数组。数组中的所有计数器最初都设置为零。
将 Value
写入索引为 Ix
的计数器。
从索引为 Ix
的计数器中减去 Decr
。
类型
函数
-spec add(Ref, Ix, Incr) -> ok when Ref :: counters_ref(), Ix :: integer(), Incr :: integer().
将 Incr
加到索引为 Ix
的计数器上。
-spec get(Ref, Ix) -> integer() when Ref :: counters_ref(), Ix :: integer().
读取计数器值。
-spec info(Ref) -> Info when Ref :: counters_ref(), Info :: #{size := Size, memory := Memory}, Size :: non_neg_integer(), Memory :: non_neg_integer().
以映射的形式返回有关计数器数组的信息。
该映射具有以下键(至少):
size
- 数组中计数器的数量。memory
- 数组的近似内存消耗(以字节为单位)。
-spec new(Size, Opts) -> counters_ref() when Size :: pos_integer(), Opts :: [Opt], Opt :: atomics | write_concurrency.
创建一个新的包含 Size
个计数器的计数器数组。数组中的所有计数器最初都设置为零。
参数 Opts
是以下可能的选项的列表:
atomics
(默认) - 计数器将具有顺序一致性。如果写入操作 A 在写入操作 B 之前按顺序完成,则并发读取器可能会看到它们中的任何一个结果、仅看到 A 或同时看到 A 和 B。它不能只看到 B 的结果。write_concurrency
- 这是一种优化,可以以每个计数器的潜在读取不一致和内存消耗为代价,实现非常高效的并发add
和sub
操作。读取操作可能会看到与并发写入操作相关的顺序不一致的结果。即使写入操作 A 在写入操作 B 之前按顺序完成,并发读取器也可能会看到 A 和 B 的任何组合,包括仅看到 B。读取操作仅保证看到在读取之前按顺序完成的所有写入。永远不会丢失任何写入,但最终都会被看到。
write_concurrency
的典型用例是,当对同一计数器的add
和sub
的并发调用非常频繁时,而对get
和put
的调用则不那么频繁。也必须可以接受缺乏绝对的读取一致性。
计数器不与当前进程绑定,并且在不再被引用时会自动进行垃圾回收。
-spec put(Ref, Ix, Value) -> ok when Ref :: counters_ref(), Ix :: integer(), Value :: integer().
将 Value
写入索引为 Ix
的计数器。
注意
尽管名称如此,
write_concurrency
优化并不会改进put
。与非常轻量级和可扩展的add
和sub
相比,调用put
是一项相对繁重的操作。write_concurrency
的put
的成本类似于没有write_concurrency
的get
加上put
。
-spec sub(Ref, Ix, Decr) -> ok when Ref :: counters_ref(), Ix :: integer(), Decr :: integer().
从索引为 Ix
的计数器中减去 Decr
。