【发布时间】:2018-06-16 10:29:09
【问题描述】:
在 log4j2 mannual link 的异步记录器中
log4j2.asyncLoggerConfigRingBufferSize 的默认值为256 * 1024
256 和 1024 在这里代表什么?
【问题讨论】:
在 log4j2 mannual link 的异步记录器中
log4j2.asyncLoggerConfigRingBufferSize 的默认值为256 * 1024
256 和 1024 在这里代表什么?
【问题讨论】:
环形缓冲区中的槽数必须是 2 的幂。这允许您不断递增计数器并使用位掩码而不是模数从计数器中获取数组索引。
例如,假设我们有一个大小为 4 的环形缓冲区。索引 0 到 3 是数组中的有效索引。我们想避免检查index++; if (index > 3) { index = 0; }。在一个紧密的循环中,这个if 检查可以减慢速度。我们可以避免吗?
是的,我们可以。我们可以直接递增而不检查,当我们从数组中获取一个值时,我们会忽略所有 4 的倍数(数组的大小)。人们经常为此使用 模 操作:value = array[index % 4];
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
...
这很好,但我们可以做得更好。模运算适用于任何数组大小,但我们选择数组大小为 2 的幂是有原因的:位掩码!位掩码可以实现同样的效果,但速度要快得多(大约快 25 倍)。
这是如何工作的?如果数组是 2 的幂,我们通过减 1 得到它的位掩码。然后我们在从数组中获取值时使用这个掩码:value = array[index & mask];
对于 4,位掩码为 4-1=3。 3 的二进制符号是11。让我们看与之前相同的示例:
0011 & 0011 = 0011 (3 & 3 = 3)
1000 & 0011 = 0000 (4 & 3 = 0)
1001 & 0011 = 0001 (5 & 3 = 1)
...
所以这与取模相同,但速度更快。同样,关键是数组必须是 2 的倍数。
回到问题:ringbuffer中实际的slot数是262144。文档声明 256 * 1024 澄清这是 2 的幂。
【讨论】: