Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
开发者_高级运维 Improve this questionI am trying to make a string with FPS showing, but, how do I actually get my programs FPS? I want to do it with
g.drawString(getFPS(), 10, 10)
How do I get my FPS?
This code does it for me. Put it in your main program loop:
//To Measure FPS
private long now;
private int framesCount = 0;
private int framesCountAvg=0;
private long framesTimer=0;
//Main Game Loop
while (isRunning)
{
//Record the time before update and draw
long beforeTime = System.nanoTime();
//... Update program & draw program...
// DRAW FPS:
now=System.currentTimeMillis();
gEngine.drawFPS(c, framesCountAvg);
framesCount++;
if(now-framesTimer>1000)
{
framesTimer=now;
framesCountAvg=framesCount;
framesCount=0;
}}
that call "gEngine.drawFPS" just tells my main draw method to include the fps at the top of the screen (and c is my Canvas) - you can use a similar method to give your "g" class the correct framesCountAvg data to draw
Calculate the time elapsed and 1000/elapsedTime
will be your fps.
Although this question sounds a little bit vague, I'll still try my best and answer it. As the original post dates back to 2011 then OP will most likely not benefit from my answer. Hopefully it'll provide better footing for those who follow, though (the previous 2 answers seem a bit too messy and laconic).
Here's a code snippet that I've often used for collecting and displaying the frame rate of various Java GUI applications:
public class FrameRateCounter {
private Map<Long, Long> measurementTimes;
public FrameRateCounter() {
measurementTimes = new HashMap<Long, Long>();
}
public synchronized void submitReading() {
long measurementTime = System.nanoTime();
long invalidationTime = System.nanoTime() + 1000000000;
measurementTimes.put(measurementTime, invalidationTime);
}
public int getFrameRate() {
performInvalidations();
return measurementTimes.size();
}
private synchronized void performInvalidations() {
long currentTime = System.nanoTime();
Iterator<Long> i = measurementTimes.keySet().iterator();
while(i.hasNext()) {
long measurementTime = i.next();
long invalidationTime = measurementTimes.get(measurementTime);
if(invalidationTime < currentTime) {
i.remove();
}
}
}
}
The obvious advantages of my approach (with regards to the previous solutions) are:
- Separation of concerns - you don't want trivial things like FPS count calculations polluting the 'main loop' of your program. Thus, isolate this logic into a separate component/class.
- Independence of the GUI component framework - it is best to steer clear of framework-dependent solutions whenever possible. In the current case this is easy - just avoid referencing things like
Graphics
orJLabel
amongst the calculations and you're good. - All measurements stored in a hashmap - Hashmaps are known for their quick look-up times (the time complexity is nearly O(1)). Thus, doing the necessary comparisons should not have any noticeable impact on the overall performance of your application.
- Can be used with multiple
javax.Swing.Timer
s or threads - callsubmitReading()
on the timer/thread whose performance you are trying to assess while runninggetFrameRate()
from another timer/thread to get the result (for example - you could write it to aJLabel
, file, etc).
(PS.: Note that with Swing, all painting operations need to be completed on the Event Dispatcher Thread (EDT). Thus, no drawing work should be delegated to other (raw) threads without the use of special commands such as SwingUtilities.invokeLater(..)
).
Hope this helps!
精彩评论