上一篇(传送门)文章把RocketMQ
的内存预热提到了一部分,但是代码层面具体的实现还会没搞彻底,今天咨询了不少人,本篇做一下总结。
public void warmMappedFile(FlushDiskType type, int pages) {
long beginTime = System.currentTimeMillis();
ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
int flush = 0;
long time = System.currentTimeMillis();
for (int i = 0, j = 0; i < this.fileSize; i += MappedFile.OS_PAGE_SIZE, j++) {
byteBuffer.put(i, (byte) 0);
// force flush when flush disk type is sync
if (type == FlushDiskType.SYNC_FLUSH) {
if ((i / OS_PAGE_SIZE) - (flush / OS_PAGE_SIZE) >= pages) {
flush = i;
mappedByteBuffer.force();
}
}
// prevent gc
if (j % 1000 == 0) {
log.info("j={}, costTime={}", j, System.currentTimeMillis() - time);
time = System.currentTimeMillis();
try {
Thread.sleep(0);
} catch (InterruptedException e) {
log.error("Interrupted", e);
}
}
}
// force flush when prepare load finished
if (type == FlushDiskType.SYNC_FLUSH) {
log.info("mapped file warm-up done, force to disk, mappedFile={}, costTime={}",
this.getFileName(), System.currentTimeMillis() - beginTime);
mappedByteBuffer.force();
}
log.info("mapped file warm-up done. mappedFile={}, costTime={}", this.getFileName(),
System.currentTimeMillis() - beginTime);
this.mlock();
}
该程序有三个点是比较有意思的:
- 如果刷盘方式为同步,则往每个pageCache写入一个字节0,并且当写入页数大于等于(1024 / 4 * 16)时刷盘;
- Thead.sleep(0) 备注为防止GC;它为何可以防止GC?这里为何要防止GC?
- mlock()方法包括mlock以及madvise;
为何要往每个pageCache也写入一个byte?
使用mmap建立内存映射后,仅仅只是建立了进程虚拟内存地址与物理内存地址之间的映射关系,但是并没有将pageCache加载至内存,写数据时如果没有命中写pageCache则发出缺页中断,为了解决该问题则往每个pageCache写入一个byte,确保在预热时就已经将pageCache加载至内存中。
Thread.sleep(0)为何可以防止GC?
咨询了一些朋友,得到了一些结论,但是似乎并没有很明确的解答,本次仅作为笔记记录。
首先,sleep(0)与yield()都是有剩余时间片让权的能力。但是sleep(0)的语义其实是陷入阻塞,进入就绪队列,从而被动让出剩余时间片,而yield()则主动建议操作系统让出本次剩余时间片,主动进入就绪队列。
除此之外,sleep(0)的语义上是将剩余时间 片让给优先级相同或者优先级更高的线程,而yield()则没有,仅仅是进入了就绪队列。
在JVM中,GC线程的级别是非常低的,让出该剩余时间片给其余的更高级别的线程可以从反面起到防止GC的目的。不管是sleep()还是yield()在JDK都没有具体的实现,所以在不同的操作系统层次上显示出来的结果可能不尽相同。具体结果后续有遇到合适的答案再做进一步解释。
此处为何要防止GC?
没有看懂具体的原因,不知道意欲何为,如果有了解的童鞋请解答一下。
mlock与madvise
请关注上一篇文章:传送门
PS: 关于prevent-gc的问题,代码已经被删除了哈,具体参照https://github.com/apache/rocketmq/issues/522
网友评论