System.nanotime返回的时间非常不同

时间:2017-11-16 08:15:50

标签: java lwjgl

所以我试图在我的游戏中实现一种昼夜循环,我正在使用System.nanotime()来获取帧之间传递的大致时间,问题是它有时会跳过大量的时间

使用lwjgl,并在启用vsync的swapBuffers之前调用Timer.update()应该是大约16.6ms增加到当前时间每个循环不应该吗?然而,它可能远远高于渲染

的实际减速

这是代码:时间等级

public class Time
{
    public static final long SECOND = 1000000000L;

    private static long lastTime;

    public static long getTime()
    {
        return System.nanoTime();
    }

    public static double getDelta()
    {
        return (double)(getTime() - lastTime) / SECOND;
    }

    public static void update()
    {
        Time.lastTime = Time.getTime();
    }
}

更新方法

    while ( !glfwWindowShouldClose(window) )
    {
        input();
        update();
        render();
    }

public void update()
{
    //System.out.println("Time since last update " + Time.getDelta());
    Time.update();
}

我正在使用增量时间:

    if ((timeOfDay + Time.getDelta()) < timeDayTotal)
        timeOfDay += Time.getDelta();
    else
        timeOfDay += Time.getDelta() - timeDayTotal;
    System.out.println("Time of day " + timeOfDay);

暂时忽略精度似乎已经过时的事实,这里有一些示例输出

Time of day 0.0077873133
Time of day 0.0077988105
Time of day 0.0078120963
Time of day 0.007860638
Time of day 0.015185255
Time of day 0.01879608
Time of day 0.01880809
Time of day 0.018820863
Time of day 0.018835938
Time of day 0.018851267

似乎主要是增加正确的数量(通过因子10 ^ -4,但足够接近,这不是问题),但是它有这些大规模的跳跃,我无法解释

最后,a)是什么问题与system.nanoTime和b)是否有修复或可行的替代?

编辑:切换到currentTimeMillis(),精度消失了,这没什么大不了的,但是跳转仍然存在

Time of day 0.03
Time of day 0.03
Time of day 0.03
Time of day 0.03
Time of day 0.06
Time of day 0.06
Time of day 0.06
Time of day 0.06

2 个答案:

答案 0 :(得分:0)

  

通常,不要在任何您不打算强烈控制其运行方式的程序中使用System.nanoTime(),以及运行它的环境。   ..

     

问题出在RDTSC指令中,该指令检索自CPU启动以来的CPU滴答数。在多核系统上,每个核心都有自己的滴答计数,并且它们不匹配,因此每次进程切换CPU时,都会得到不同的测量值。由于某些电源管理系统实际上会改变CPU的频率以节省功率,这一问题更加复杂,即使在单核,单CPU系统上也会破坏功能。

来自here

答案 1 :(得分:0)

从您发布的代码中,看起来您在渲染之前更新()每帧上的时间,那么当您使用getDelta()时,您只测量到达那里所花费的时间,而不是整个帧时间?

我认为它看起来应该更像这样:

public class Time
{
    public static final long SECOND = 1000000000L;
    public static final double timeDayTotal = 100.0; // ?

    private static final long start = System.nanoTime();
    private static double timeOfDay;

    public static void update() {
        long now = System.nanoTime();
        timeOfDay = (now - start) / (double)SECOND % timeDayTotal;
    }

    public static double getTimeOfDay()
    {
        return timeOfDay;
    }
}