При исследовании результата теста производительности я обнаружил следующую трассировку стека в Java Flight Recorder "Горячие методы":
Stack Trace Sample Count Percentage(%)
----------- ------------ ----------
java.util.Arrays.rangeCheck(int, int, int) 358 2.212
java.util.Arrays.fill(char[], int, int, char) 358 2.212
java.lang.AbstractStringBuilder.setLength(int) 358 2.212
java.lang.StringBuilder.setLength(int) 358 2.212
org.apache.logging.log4j.core.async.RingBufferLogEvent.getMessageTextForWriting()
201 1.242
org.apache.logging.log4j.core.async.RingBufferLogEvent.setMessage(Message)
201 1.242
Из трассировки стека это выглядит так, как если бы результат строки StringBuilder вызывался при вызове Arrays.fill
. Однако я не понимаю, почему это происходит, потому что длина StringBuilder установлена на ноль.
Глядя на код для метода Log4j RingBufferLogEvent.getMessageTextForWriting
, ясно, что длина StringBuilder никогда не устанавливается ни на какое другое значение, кроме нуля:
// RingBufferLogEvent.java
private StringBuilder getMessageTextForWriting() {
if (messageText == null) {
messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE); // 128
}
messageText.setLength(0); // <-- this call. Note: new length is ALWAYS zero.
return messageText;
}
Я не понимаю, как это может привести к вызову Arrays.fill
. Если посмотреть на код для AbstractStringBuilder
, Arrays.fill
должен вызываться только в том случае, если новая длина больше, чем предыдущее количество символов.
// AbstractStringBuilder.java
public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
ensureCapacityInternal(newLength);
if (count < newLength) { // <-- how can this condition be true if newLength is zero?
Arrays.fill(value, count, newLength, '\0');
}
count = newLength;
}
Как count < newLength
когда-либо true
когда newLength
всегда равен нулю?
Версия JVM:
Java HotSpot (TM) 64-разрядная серверная VM (25.144-b01) для linux-amd64 JRE (1.8.0_144-b01), построенная 21 июля 2017 21:57:33 с помощью "java_re" с gcc 4.3.0 20080428 (Red Hat 4.3.0-8)
(и Log4j 2.10.0)