1

我对rocketmq做了一个负载测试,然后我发现了很多长调用,长调用花费超过100ms。但是我阅读了长调用的源代码,主要成本是字节缓冲区的写入。核心代码如下:

public AppendMessageResult doAppend(final long fileFromOffset,
     final ByteBuffer byteBuffer, final int maxBlank, 
     final MessageExtBrokerInner msgInner) {//from CommitLog.java
    ...
    final long beginTimeMills = CommitLog.this.defaultMessageStore.now();
    byteBuffer.put(this.msgStoreItemMemory.array(), 0, msgLen);

    AppendMessageResult result = new AppendMessageResult(AppendMessageStatus.PUT_OK, wroteOffset, msgLen, msgId,
        msgInner.getStoreTimestamp(), queueOffset, CommitLog.this.defaultMessageStore.now() - beginTimeMills);
    return result;
}

日志显示CommitLog.this.defaultMessageStore.now() - beginTimeMills(下面日志中的 pagecacheRT)花费超过 100 毫秒。

2018-04-09 00:24:41 WARN SendMessageThread_1 - [NOTIFYME]putMessage in lock cost time(ms)=517 nano time(ms)=516, bodyLength=130 AppendMessageResult=AppendMessageResult{status=PUT_OK, wroteOffset=3113603972920, wroteBytes=128, msgId='0A0C240300002A9F000002D4F1423F38', storeTimestamp=1523204680621, logicsOffset=11016755, pagecacheRT=517, msgNum=1}

是put操作的时间成本。然后pagecacheRT我看到了byteBuffer的初始化代码,像这样:

public void init() {
        for (int i = 0; i < poolSize; i++) {
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(fileSize);

            final long address = ((DirectBuffer) byteBuffer).address();
            Pointer pointer = new Pointer(address);
            LibC.INSTANCE.mlock(pointer, new NativeLong(fileSize));

            availableBuffers.offer(byteBuffer);
        }
    }

字节缓冲区只是一个直接缓冲区。我的测试环境是一台32处理器和96G内存的物理机,写入字节为125字节预写入。我在负载测试的时候看到监视器,CPU和磁盘都很健康。我不认为这个问题是由rocketmq的工具造成的。因为主要代码很简单,只是上面的部分代码。

但是我不明白为什么写记忆会花费这么多时间。有什么办法可以理解这些吗?

提前致谢!

4

0 回答 0