如何减少Java的抖动?

Pet*_*rey 24 java linux real-time

为解决此问题,我创建了一个开源Java Thread Affinity库

当我有许多线程密切交互时,它可以减少延迟并增加吞吐量.对于单线程任务,它仍然可以减少相当多的抖动.


该程序查看调用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上报告

Time jumped 2,905 / 131 / 20 times by at least 10 / 100 / 1,000 us in 120.0 seconds   
Run Code Online (Sandbox Code Playgroud)

我试图chrt设置实时优先级并taskset尝试在启动过程后锁定到单个核心,但这些并没有像我预期的那样有帮助.

我配置了该框以将所有中断移至cpus 0-3,并将所有进程的cpu掩码移至0xFF至0x0F.在top第一四个CPU是〜99%闲置和最后四个CPU是100.0%处于闲置状态.

chrt -r 99以root身份使用

Time jumped 673 / 378 / 44 times by at least 10 / 100 / 1,000 us in 120.0 seconds 
Run Code Online (Sandbox Code Playgroud)

但是,taskset -c 7单独使用时(我确保cpu7是免费的)

Time jumped 24 / 1 / 0 times by at least 10 / 100 / 1,000 us in 120.0 seconds 
Run Code Online (Sandbox Code Playgroud)

运用 chrt - r 99 taskset -c 7

Time jumped 7 / 1 / 0 times by at least 10 / 100 / 1,000 us in 120.0 seconds  
Run Code Online (Sandbox Code Playgroud)

似乎在进程启动后尝试使用taskset对我来说不起作用.

更广泛的问题是;

如何减少Java进程的抖动?还有更多关于减少Linux抖动的技巧吗?

注意:在此过程运行期间不会发生GC(使用-verbosegc检查)

看起来代码编译可能会在100 - 102 ms后每次导致3.62 ms的延迟.出于这个原因,我在第一秒中忽略了所有内容作为预热.

Mat*_*att 17

有系统抖动和JVM抖动.

对于前者,您可以在启动时使用isolcpus参数来确保除了您的应用程序代码之外什么都不能在那些cpu上运行

http://www.novell.com/support/viewContent.do?externalId=7009596&sliceId=1

理想情况下,你sched_setaffinity只需要为活动线程进行jni调用(对你自己的jni lib),这样你就什么都没有,只有那个线程在那里运行.

根据我的经验,系统抖动通过使用isolcpus最小化,中断仅由特定内核处理,超线程关闭,绝对所有使用的电源管理都被删除(当它们可用于关闭所有c状态时,这些是bios选项&p-state management)在屏蔽核心上运行您的应用程序.bios特定选项显然特定于您的主板,因此您需要根据您的主板型号进行调查.

另一件看系统级别的是本地APIC中断(LOC,本地中断计数器)频率.这是一个使用1kHz中断的"低延迟桌面"吗?无论哪种方式,您都可以预期抖动会在中断间隔周围聚集

我知道几乎没有什么,但我知道作为抖动的来源; 内核tlb刷新中断和用户空间tlb刷新中断.一些RT内核提供了控制这些内容的选项,因此这可能是另一件需要考虑的事情.您还可以查看此站点有关在RT内核上构建RT应用程序的更多提示.