【发布时间】:2011-12-29 17:41:24
【问题描述】:
为了解决这个问题,我创建了一个开源Java Thread Affinity library
当我有多个线程密切交互时,它可以减少延迟并提高吞吐量。对于单线程任务,它仍然可以减少相当多的抖动。
此程序查看调用 System.nanoTime() 之间的时间差异并报告超过 10x,000 ns 的时间差异。
public class TimeJumpingMain {
static final long IGNORE_TIME = 1000 * 1000 * 1000; // the first second to allow warmup.
static final int minJump = 10; // smallest jump of 10 us.
static final int midJump = 100; // mid size jump of 100 us.
static final int bigJump = 1000; // big jump of 1 ms.
public static void main(String... args) {
int[] intervalTimings = new int[1000];
int[] jumpTimings = new int[1000];
long start = System.nanoTime();
long prev = start;
long prevJump = start;
int jumpCount = 0;
int midJumpCount = 0;
int bigJumpCount = 0;
while (true) {
long now = System.nanoTime();
long jump = (now - prev) / 1000;
if (jump > minJump && now - start > IGNORE_TIME) {
long interval = (now - prevJump) / 1000;
if (jumpCount < intervalTimings.length) {
intervalTimings[jumpCount] = (int) interval;
jumpTimings[jumpCount] = (int) jump;
}
if (jump >= midJump)
midJumpCount++;
if (jump >= bigJump)
bigJumpCount++;
prevJump = now;
jumpCount++;
}
prev = now;
if (now - start > 120L * 1000 * 1000 * 1000 + IGNORE_TIME)
break;
}
System.out.println("interval us\tdelay us");
for (int i = 0; i < jumpCount && i < intervalTimings.length; i++) {
System.out.println(intervalTimings[i] + "\t" + jumpTimings[i]);
}
System.out.printf("Time jumped %,d / %,d / %,d times by at least %,d / %,d / %,d us in %.1f seconds %n",
jumpCount, midJumpCount, bigJumpCount, minJump, midJump, bigJump, (System.nanoTime() - start - IGNORE_TIME) / 1e9);
}
}
在我的机器上报告
Time jumped 2,905 / 131 / 20 times by at least 10 / 100 / 1,000 us in 120.0 seconds
我尝试chrt 设置实时优先级,taskset 尝试在启动进程后锁定到单个核心,但这些都没有像我预期的那样有帮助。
我将框配置为将所有中断移动到 cpu 0-3,并将所有进程的 cpu 掩码从 0xFF 移动到 0x0F。在top 中,前四个 cpu 大约 99% 空闲,最后四个 cpu 空闲 100.0%。
使用chrt -r 99 作为根
Time jumped 673 / 378 / 44 times by at least 10 / 100 / 1,000 us in 120.0 seconds
但是,当单独使用taskset -c 7 时(我已经确定 cpu7 是免费的)
Time jumped 24 / 1 / 0 times by at least 10 / 100 / 1,000 us in 120.0 seconds
使用chrt - r 99 taskset -c 7
Time jumped 7 / 1 / 0 times by at least 10 / 100 / 1,000 us in 120.0 seconds
似乎在进程开始后尝试使用任务集对我不起作用。
更广泛的问题是;
如何减少 Java 进程的抖动?还有其他减少 Linux 抖动的技巧吗?
注意:此进程运行期间不会发生 GC(使用 -verbosegc 检查)
似乎代码编译在 100 - 102 ms 之后每次可能会导致 3.62 ms 的延迟。出于这个原因,我忽略了第一秒的所有内容作为热身。
【问题讨论】:
-
尽量不要在热循环中打印,只需将结果添加到arraylist中以减少系统调用。你也检查了编译器的启动吗?
-
似乎在进程开始后尝试使用任务集对我不起作用。我从来没有设法让它工作(之后),所以如果我需要 CPU我依赖于预先选择它。