问题
In async logger of log4j2 mannual link
default value of log4j2.asyncLoggerConfigRingBufferSize
is 256 * 1024
What does 256
and 1024
represent here?
回答1:
The number of slots in the ringbuffer needs to be a power of 2. This allows you to keep incrementing the counter and use a bitmask instead of modulo to get the array index from the counter.
For example, suppose we have a ringbuffer of size 4. Indexes 0
to 3
are valid indexes into the array. We want to avoid checking index++; if (index > 3) { index = 0; }
. In a tight loop this if
check can slow things down. Can we avoid it?
Yes we can. We can just increment without checking, and when we get a value from the array we ignore all multiples of 4 (the size of the array). Often people use the modulo operation for this: value = array[index % 4];
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
...
This works fine, but we can do better. The modulo operation works for any array size, but we chose the array size to be a power of two for a reason: bit masks! A bit mask can achieve the same thing, but much, much faster (about 25 times as fast).
How does this work? If the array is a power of two, we get its bit mask by subtracting one. We then use this mask when getting values from the array: value = array[index & mask];
For 4, the bit mask is 4-1=3. 3 in binary notation is 11
. Let’s look at the same example as before:
0011 & 0011 = 0011 (3 & 3 = 3)
1000 & 0011 = 0000 (4 & 3 = 0)
1001 & 0011 = 0001 (5 & 3 = 1)
...
So this does the same as taking the modulo but faster. Again, key point is that the array needs to be a multiple of 2.
Back to the question: The actual number of slots in the ringbuffer is 262144
. The documentation states 256 * 1024
to clarify that this is a multiple of 2.
来源:https://stackoverflow.com/questions/50887089/understand-ring-buffer-in-async-logger