首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >超过最大FPS

超过最大FPS
EN

Stack Overflow用户
提问于 2015-02-09 22:52:20
回答 3查看 153关注 0票数 2

我正在试图计算我的程序的FPS。虽然给定的最大FPS是超限,但我无法解释原因。我用MAX_FPS设置为60对它进行了测试,我总是得到关于63显示的信息。

代码语言:javascript
复制
{...}
int frameCount = 0;
long time = System.currentTimeMillis();
while(running) {
    try {
        {...} // do something
        Thread.sleep(1000 / MAX_FPS);
        frameCount++;
        if (System.currentTimeMillis() - time >= 1000) {
            {...} // display FPS w/ frameCount
            frameCount = 0;
            time = System.currentTimeMillis();
        }
    } catch (InterruptedException ex) {
        System.err.println(ex.toString());
    }
}
{...}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-10 00:02:33

根据NESPowerGlove的答案,达到目标FPS的问题是,您必须选择一个整数值来调用Thread.sleep() --如果您选择16,您将得到大约63 FPS;如果您选择17,您将得到大约58 FPS。

对此,我可以想到两种解决方案:

  1. 实现某种负反馈回路来控制FPS。例如,我发现以下PI (比例+积分)控制器使FPS保持在60左右: 最后long sleepTime =(长) (1000.0 / TARGET_FPS);System.out.println(“睡眠时间为”+ sleepTime);System.out.println= System.nanoTime();long delta = 0;double cumulativeFpsError = 0.0;for (int frameCount = 0;true;++frameCount) { Thread.sleep(( long ) (sleepTime + delta));System.out.println= System.nanoTime() - time;if ( frameCount >= 1_000_000_000) { double >=1_000_000_000= (double) frameCount* 1e9;System.out.println (fps );cumulativeFpsError += (fps - 60);增量+= (fps- TARGET_FPS) * 0.55 + 0.14 * cumulativeFpsError;frameCount = 0;时间+=累计;}

0.55值和0.14值均经反复试验确定.更好的值可能是可用的(但至少它似乎大致稳定)。fps产出:

代码语言:javascript
复制
61.08042479827653
61.817816897275485
58.42717726642977
62.0654826347193
58.43759367657694
62.07263954479402
58.444556146850026
62.05489635777375
58.4438970272065
62.05784933619571
58.45590905841833
62.069491426232766
58.44381852435569
62.07438904528996
...

实际上,积分项没有多大作用--大概是因为睡眠值只能在大小为1的步骤中变化。

  1. 使用一种不同的方法来睡眠一段更精确的时间。例如,How to suspend a java thread for a small period of time, like 100 nanoseconds?提出了一些替代方案,比如轮询System.nanoTime(),直到超过某个截止日期。例如: long time = System.nanoTime();for (int frameCount = 0;true;++frameCount) { long end = System.nanoTime() + ( long ) (1_000_000_000.0 / TARGET_FPS);while (System.nanoTime() < end);long time= System.nanoTime() - time;if ( frameCount >= 1_000_000_000) { double fps = (double) frameCount / elapsed * 1e9;System.out.println(fps);frameCount= 0;时间= System.nanoTime();}

这似乎是更好的工作,FPS徘徊在60以下:

代码语言:javascript
复制
58.99961555850502
59.99966304189236
59.99942898543434
59.99968068169941
59.99968770162551
59.99919595077507
59.99945862488483
59.999679241714766
59.99753134157542
59.99963898217224
59.999265728986
...

这样做的缺点可能是while循环会很热。

当然,您可以采用某种混合方法,在大部分等待时间使用Thread.sleep,然后使用热while循环来获得更精确的延迟。

票数 1
EN

Stack Overflow用户

发布于 2015-02-09 22:59:49

1000 / 60在整数数学中是16,1000 / 16大约是62.5。假设线程确实睡了将近16毫秒(也许更少一点),如果你的循环没有花那么长时间执行一次迭代,如果到最后一个帧的第二个时间是999毫秒,允许另一个更新溜进来,那么循环每秒可以完成63次迭代是有意义的。

票数 2
EN

Stack Overflow用户

发布于 2015-02-09 23:11:07

您可能需要使用System.nanoTime()代替。不是为了任何额外的精度,而是因为它是一种更正确的方法来测量经过的时间。参见Kevin对How do I measure time elapsed in Java?的回答。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28421016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档