在新的PC上运行Java绘图基准测试(Core i7-4820K 3.7 GHz,Asus P9X79 LE,GeForce GTX 650,Windows 8.1和Ubuntu 14.04)似乎使用vsync在大约60 FPS下通过Windows与Java RTE 1.7运行。 0_65。然后,在稍后的情况下,基于其他PC上的速度,以预期的400+ FPS运行。现在又回到了60 FPS。 GPU利用率几乎为0%,GPU在最轻的测试中<10%。新的图形驱动程序没有任何区别。同一个类文件通过Ubuntu使用linux java 1.7.0_55获得400 FPS,并且没有使用JDK 6或7编译。
下面是没有加载,计算和显示图像的功能的代码。在较旧的稍慢的Win 7 PC上获得近600 FPS,但在新PC上再获得60 FPS。通过HTML小程序在线运行的代码的变体运行速度为400+ FPS。有人有解释吗?
// Save as JavaDrawIt.java
// Compile command - javac JavaDrawIt.java
// Run command - java JavaDrawIt
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class JavaDrawIt extends JPanel implements ActionListener
{
Timer timer;
static int WIDTH = 1280 ;
static int HEIGHT = 720 ;
int gch = 1;
int gcm = 1;
int grn = 0;
String msg;
double fps;
double startTime;
double runTime = 0;
int frames = 0;
Random randNum = new Random();
private JavaDrawIt()
{
randNum.setSeed(999);
timer = new Timer(0, this);
startTime = (double)System.currentTimeMillis();
}
public void actionPerformed(ActionEvent e)
{
if (runTime <= 5.0)
{
repaint();
}
}
public void paintComponent(Graphics g)
{
int i;
float fh;
float fw;
super.paintComponent(g);
grn = grn + gch;
if (grn > 255)
{
gch = -gcm;
grn = 255;
}
if (grn < 1)
{
gch = gcm;
grn = 0;
}
g.setColor(new Color(0, grn, 255));
g.fillRect(0, 0, WIDTH, HEIGHT);
frames = frames + 1;
Graphics2D g2 = (Graphics2D)g;
Font font = new Font("MONOSPACE", Font.PLAIN, 24);
g2.setFont(font);
g.setColor (Color.WHITE);
runTime = ((double)System.currentTimeMillis() - startTime) / 1000;
fps = (double)frames / runTime;
msg = String.format(" %6.2f FPS, %6d Frames, %6.2f Seconds", fps, frames, runTime);
g2.drawString(msg, 10, 30);
}
public static void main(String[] args)
{
JFrame f = new JFrame(" JavaDrawIt");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JavaDrawIt m = new JavaDrawIt();
f.add(m);
f.setSize(WIDTH, HEIGHT);
f.setVisible(true);
m.timer.start();
}
}
我尝试了一些“线程安全”示例,试图在新PC上获得更快的FPS速度,但没有任何成功。最后一个只是刷新一个没有图形的空白屏幕。我注意到测量的FPS通常高达65 FPS,这表明它可能不是强制VSYNC。这导致怀疑Swing Timer,我发现它可以校准,如下所示,还包括sleep,wait,currentTimeMillis和nanoTime。
http://www.java2s.com/Code/Java/Swing-JFC/TimeResolution.htm
以下产生摆动定时器测量:
// TimeResolution.java
// Copyright (c) 2007, Sun Microsystems, Inc
// All rights reserved.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class TimeResolution implements ActionListener
{
private static int INCREMENT = 5;
private static int MAX = 50;
// Variables used in measurement of Swing timer
int timerIteration = 0;
int iterations = 0;
Timer timer;
long startTime, endTime;
int sleepTime;
public void actionPerformed(ActionEvent ae)
{
if (++timerIteration > iterations)
{
timer.stop();
timerIteration = 0;
endTime = System.nanoTime();
long totalTime = (endTime - startTime) / 1000000;
float calculatedDelayTime = totalTime / (float)iterations;
System.out.printf(" %2d %5d %5d %5.2f\n",
sleepTime, iterations, totalTime, calculatedDelayTime);
}
}
public void measureTimer()
{
System.out.printf(" measured\n");
System.out.printf("timer delay iterations total time per-delay\n");
for (sleepTime = 0; sleepTime <= 5; ++sleepTime)
{
iterations = (sleepTime == 0) ? 1000 : (1000 / sleepTime);
timerIteration = 1;
timer = new Timer(sleepTime, this);
startTime = System.nanoTime();
timer.start();
while (timerIteration > 0)
{
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
}
}
}
}
// Execute the various timer resolution tests.
public static void main(String args[])
{
TimeResolution timeResolution = new TimeResolution();
timeResolution.measureTimer();
}
}
以下显示了产生快速FPS的PC的结果,以及来自新PC的第二个结果。睡眠时间为零时,另一台PC产生0.11毫秒,新的一台产生15.66毫秒,相当于接近64 FPS,前者限制为9091 FPS。
有谁知道是否可以强制使用最小摆动计时器分辨率?
Other PC
timer delay iterations total time per-delay
0 1000 113 0.11
1 1000 15600 15.60
2 500 7800 15.60
3 333 5195 15.60
4 250 3900 15.60
5 200 3120 15.60
New PC
0 1000 15660 15.66
1 1000 15625 15.63
2 500 7812 15.62
3 333 5203 15.62
4 250 3906 15.62
5 200 3125 15.63
答案 0 :(得分:0)
我相信这是一个完整的答案(前面已经低估了)。我希望有人在这里知道,但事实并非如此。所以我不得不做自己的研究。
在使用Javax swing timer = new Timer(0,this)时,在指示actionPerformed后,主要活动执行应该以零睡眠时间重新开始。我找到了一个简单的程序,它演示了时序,没有图形活动,并修改它来测量单个动作(帧)和每秒累积帧数所用的时间。结果如下。
几帧之后,有问题的PC切换到15.3+ ms的常规休眠时间,可能正如另一条消息中所报告的那样,由Windows时间片粒度1000 ms / 64或15.625 ms控制,另一台PC表示高开头的开销,但在50帧内录得543 FPS。
New PC Win 8.1 Other PC Win 7
Frames FPS This frame FPS This frame
microsecs microsecs
1 500 2603 166 6170
2 44 42630 333 100
3 57 7051 500 107
4 58 15402 571 74
5 60 15550 555 231
6 60 15633 117 41586
7 60 15483 134 817
8 61 15396 106 22895
9 61 15388 107 8374
10 61 15370 117 867
11 62 15321 129 41
12 62 15418 141 217
13 62 15390 152 88
14 62 15353 162 73
To
45 63 15353 494 45
46 63 15360 505 48
47 63 14998 516 45
48 63 15306 521 113
49 63 15331 532 64
50 63 15365 543 44
Java程序如下。
// From http://www.java2s.com/Code/JavaAPI/javax.swing/Timerstop.htm
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
class MainClass extends JFrame
{
Timer timer;
long startTime, startTimeF, runTime, fps, usecs;
int counter;
MainClass(String title)
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener a = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
runTime = (System.nanoTime() - startTime) / 1000000;
usecs = (System.nanoTime() - startTimeF) / 1000;
fps = counter * 1000 / runTime;
System.out.println(" Frames = " + counter + " " + fps + " FPS This frame " + usecs + " microseconds");
startTimeF = System.nanoTime();
if (++counter > 50)
{
timer.stop();
System.exit(0);
}
}
};
timer = new Timer(0, a);
startTime = System.nanoTime();
startTimeF = System.nanoTime();
counter = 1;
timer.start();
setSize(800, 600);
// pack();
setVisible(true);
}
public static void main(String[] args)
{
new MainClass("Timer Demo1");
}
}