Would this lower frame rate? - java

I am making a game, and the requirement is to make it have at least 30FPS and shouldn't drop below. Would what I have below achieve this? Or am I off somewhere? Much help would be appreciated.
private long period = 6 * 1000000;
private static final int DELAYS_BEFORE_YIELD = 5;
long before, after, difference, sleep, oversleep = 0;
int delays = 0;
while (running)
{
before = System.nanoTime();
after = System.nanoTime();
difference = after - before;
if (sleep < period && sleep > 0)
{
try
{
Thread.sleep(sleep / 35000L);
oversleep = 0;
}
catch (InterruptedException e)
{
}
}
else if (difference > period)
{
oversleep = difference - period;
}
else if (++delays >= DELAYS_BEFORE_YIELD)
{
Thread.yield();
oversleep = 0;
delays = 0;
}
else
{
oversleep = 0;
}
}

You can set an upper bound to frame rate but not a lower bound that is guaranteed to be always followed.
You can make a function be called no more than 30 times per second but you can't be sure it will be called at least 30 times per second. At 30 fps you have 0.03s of time that will be distributed between your threads and usually the drawing one is the heaviest between them all (unless you have complex operations like AI or whatever but that should be solved by lowering their rate or precomputing what can be precomputed).
If time of draw + time of logic > 0.03 then there is no way to make your game run at least at 30fps.

Good that you are asking early, because one better uses a timer I think. And that turns things inside out. (It could be done your way though.)
Sorry for this non-answer, but I think it is a worthwhile advice.
Look into some game/animation frameworks for their approach.

Related

How to run a For Loop for 60 seconds maximum irrespective of the size of the loop and complete all the iterations

for(i=1;i<list.size();i++){
//do something
//For Eg: move marker to a new position on the map
}
I want the above loop to complete all the iterations irrespective of the size of the list and also want the entire task to run for 1 minute. (60 seconds)
I don't really know if this is what you want but I hope this helps.
import java.util.concurrent.TimeUnit;
for(i=1;i<list.size();i++){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute thing you want to be executed every second
}
As explanation: you iterate through the for loop and the thread waits for one second before executing the code after the TimeUnit.SECONDS.sleep(1);.
If the list's size is 60 it would therefore take a minute for the loop to end.
Edit: It has occurred to me that it might be smarter to do a try-catch around the sleep function.
You can, for example, use System.nanoTime() to measure the duration of your loop, and then use TimeUnit.NANOSECONDS.sleep(...) to make it wait for the rest of time like this:
long start = System.nanoTime();
long desiredDuration = 60 * 1000 * 1000;
// your loop goes here
long duration = System.nanoTime() - start;
if (duration < desiredDuration)
TimeUnit.NANOSECONDS.sleep(desiredDuration - duration);
The best possible solution is to compute the desired time first and then run the loop to that extent.
long finish=System.currentTimeMillis() + 60000;
while(System.currentTimeMillis() != finish)
{
//statements;
//statements;
}
If you are trying to equip the CPU and keep it idle for this time the process is known as busy waiting but is not considered convenient in many cases so i recommend to use Thread.sleep(duration) for this purpose.
Would like to receive further queries from your side.
To spread N amount of invocations uniformly across a minute, you'll have to set the delay in between the invocations to the value 60/(N-1). The -1 is optional but causes the first and last invocations to be exactly 60 seconds apart. (just like how a ladder with N rungs has N-1 spaces)
Of course, using sleep() with the number calculated above is not only subject to round-off errors, but also drift, because you do stuff between the delays, and that stuff also takes time.
A more accurate solution is to subtract the time at which each invocation should occur (defined by startTime + 60*i/(N-1)) from the current time. Reorder and reformulate those formulas and you can subtract the 'time that should have elapsed for the next invocation' from the already elapsed time.
Of course 'elapsed time' should be calculated using System.nanoTime() and not System.currentTimeMillis() as the latter can jump when the clock changes or the computer resumes from stand-by.
For this example I changed 60 seconds to 6 seconds so you can more easily see what's going on when you run it.
public static void main(String... args) throws Exception {
int duration = 6; // seconds
List<Double> list = IntStream.range(0, 10).mapToDouble(i->ThreadLocalRandom.current().nextDouble()).boxed().collect(Collectors.toList());
long startTime = System.nanoTime();
long elapsed = 0;
for (int i = 0; i < list.size(); i++) { // Bug fixed: start at 0, not at 1.
if (i > 0) {
long nextInvocation = TimeUnit.NANOSECONDS.convert(duration, TimeUnit.SECONDS) * i / (list.size() - 1);
long sleepAmount = nextInvocation - elapsed;
TimeUnit.NANOSECONDS.sleep(sleepAmount);
}
elapsed = System.nanoTime() - startTime;
doSomething(elapsed, list.get(i));
}
}
private static void doSomething(long elapsedNanos, Double d) {
System.out.println(elapsedNanos / 1.0e9f + "\t" + d);
}
Of course when the task you preform per list element takes longer than 60/(N-1) seconds, you get contention and the 'elapsed time' deadlines are always exceeded. With this algorithm the total time just taking longer than a mnute. However if some earlier invocations exceed the deadline, and later invocations take much less time than 60/(N-1), this algorithm will show 'catch-up' behavior. This can be partially solved by sleeping at least a minimum amount even when sleepAmount is less.
Check out this.
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
int i = 0;
while (System.currentTimeMillis() < end)
{
// do something, iterate your list
i++;
if (i == list.size()) { // check size of the list if iteration is completed
// if time has not yet expired, sleep for the rest of the time
Thread.sleep(end - System.currentTimeMillis());
}
}
Do not forget checking size of the list.

How to calculate cpu usage for process java (JavaSysMon) [duplicate]

Is there a way in monitoring CPU usage using pure Java?
There is a gem in the comments on the article which kgiannakakis linked:
javasysmon
JavaSysMon manages processes and
reports useful system performance
metrics cross-platform. You can think
of it as a cross-platform version of
the UNIX `top’ command, along with the
ability to kill processes. It comes in
the form of a single JAR file /..
-works on Windows, Mac OS X, Linux, and Solaris.
How about using jmx mbeans?
final OperatingSystemMXBean myOsBean=
ManagementFactory.getOperatingSystemMXBean();
double load = myOsBean.getSystemLoadAverage();
You can use jMX beans to calculate a CPU load. Note that this measures CPU load of your java program, not the overall system load. (the question didn't specify which)
Initialize:
ThreadMXBean newBean = ManagementFactory.getThreadMXBean();
try
{
if (this.newBean.isThreadCpuTimeSupported())
this.newBean.setThreadCpuTimeEnabled(true);
else
throw new AccessControlException("");
}
catch (AccessControlException e)
{
System.out.println("CPU Usage monitoring is not available!");
System.exit(0);
}
Then as your loop (assuming your application uses a loop, otherwise what's the point in measuring CPU usage?) use this:
long lastTime = System.nanoTime();
long lastThreadTime = newBean.getCurrentThreadCpuTime();
while (true)
{
// Do something that takes at least 10ms (on windows)
try
{
int j = 0;
for (int i = 0; i < 20000000; i++)
j = (j + i) * j / 2;
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
// Calculate coarse CPU usage:
long time = System.nanoTime();
long threadTime = newBean.getCurrentThreadCpuTime();
double load = (threadTime - lastThreadTime) / (double)(time - lastTime);
System.out.println((float)load);
// For next iteration.
lastTime = time;
lastThreadTime = threadTime;
}
You need to use double precision because a long doesn't fit in a float (though it might work 99.9999999999999999% of the time)
If the 'something' you're doing takes less than approximately 1.6ms (Windows), then the returned value will not even have increased at all and you'll perpetually measure 0% CPU erroneously.
Because getCurrentThreadCpuTime is VERY inaccurate (with delays less than 100ms), smoothing it helps a lot:
long lastTime = System.nanoTime();
long lastThreadTime = newBean.getCurrentThreadCpuTime();
float smoothLoad = 0;
while (true)
{
// Do something that takes at least 10ms (on windows)
try
{
int j = 0;
for (int i = 0; i < 2000000; i++)
j = (j + i) * j / 2;
Thread.sleep(10);
}
catch (InterruptedException e)
{
}
// Calculate coarse CPU usage:
long time = System.nanoTime();
long threadTime = newBean.getCurrentThreadCpuTime();
double load = (threadTime - lastThreadTime) / (double)(time - lastTime);
// Smooth it.
smoothLoad += (load - smoothLoad) * 0.1; // damping factor, lower means less responsive, 1 means no smoothing.
System.out.println(smoothLoad);
// For next iteration.
lastTime = time;
lastThreadTime = threadTime;
}
This is not possible using pure Java. See this article for some ideas.
Maybe if stuck, you might 'sense' cpu availability by running an intermittent bogomips calculator in a background thread, and smoothing and normalising its findings.
...worth a shot no :?
if you are using linux - just use jconsole - you will get all the track of java memory management

Exact timing in Java game loop

I'm developing a network based game, and I'm now focusing on the server side simulation. Of course I need a game loop, and I opted for a fixed timestep loop so that it will be far easier to reproduce on the client(s) than a variable timestep one. I also decided to run my game at 60 Hz. This is the game logic speed, not rendering speed. Rendering will be handled with a variable timestep loop in the clients to have the best possible rendering.
The server is written in Java.
I already made an example game loop using code from http://www.java-gaming.org/index.php?topic=24220.0 and modifying the loop with my code. Here is the loop:
private void gameLoop()
{
final double GAME_HERTZ = 60.0;
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
long extraSleepTime = 0;
while (running)
{
int updateCount = 0;
if (!paused)
{
long loopStartTime = System.nanoTime();
updateGame();
updateCount++;
long timeAfterUpdate = System.nanoTime();
lastUpdateTime = timeAfterUpdate;
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((loopStartTime - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
drawGame(interpolation);
lastRenderTime = loopStartTime;
//Update the frames we got.
int thisSecond = (int) (lastUpdateTime / 1000000000);
if (thisSecond > lastSecondTime)
{
long nanoTime = System.nanoTime();
System.out.println("NEW SECOND " + thisSecond + " " + frameCount + ": " + (nanoTime - lastNanoTime));
lastNanoTime = nanoTime;
fps = frameCount;
frameCount = 0;
lastSecondTime = thisSecond;
}
long loopExecutionTime = timeAfterUpdate - loopStartTime;
long sleepTime = (long)TIME_BETWEEN_UPDATES - loopExecutionTime - extraSleepTime;
// Only sleep for positive intervals
if(sleepTime >= 0)
{
try
{
Thread.sleep(sleepTime / 1000000);
}
catch(InterruptedException e) {}
}
else
{
System.out.println("WARN: sleepTime < 0");
}
// Counts the extra time that elapsed
extraSleepTime = System.nanoTime() - timeAfterUpdate - sleepTime;
}
}
The problem is that, when running, the FPS aren't stable at 60Hz, but sometimes go lower. For example I sometimes get 58-59Hz, going as low as 57Hz.
This variability wouldn't be a problem if the game was run locally, but as our game is networked, I need to keep the exact time so that I can reproduce the logic calculations on both client and server.
Is there any error in this code, or anything that could be improved to make it more stable? Our goal is 60Hz being kept exactly all the time.
EDIT: A first solution that came up in my mind is running the loop a bit faster than it needs to, for example at 70Hz, and checking the frame count to limit the updates to 60 per seconds. This way the simulation would be run in bursts and would need buffering, (up to 60 frames at a time), but should be able to never be slower than needed.
Thanks in advance.
If you want to achieve 60 frames per second, you'd be better off using a scheduled executor as Thread.sleep() may not be as precise as you'd like it to be. Consider the following sample for your server code: (Please note it contains Java 8 code)
public void gameLoop() {
// game logic here
}
Executors.newSingleThreadScheduledExecutor()
.scheduleAtFixedRate(this::gameLoop, 0, 16, TimeUnit.MILLISECONDS)
It will run your gameLoop() every 16 milliseconds which is essentially what you want. This should give you much more precise results. You can also replace 16 and TimeUnit.MILLISECONDS with their nanoseconds counterpart, even though it shouldn't make any noticeable difference

Java strange performance inconsistency

I have a simple recursive method, a depth first search. On each call, it checks if it's in a leaf, otherwise it expands the current node and calls itself on the children.
I'm trying to make it parallel, but I notice the following strange (for me) problem.
I measure execution time with System.currentTimeMillis().
When I break the search into a number of subsearches and add the total execution time, I get a bigger number than the sequential search. I only measure execution time, no communication or sync, etc. I would expect to get the same time when I add the times of the subtasks. This happens even if I just run one task after the other, so without threads. If I just break the search into some subtasks and run the subtasks one after the other, I get a bigger time.
If I add the number of method calls for the subtasks, I get the same number as the sequential search. So, basically, in both cases I do the same number of method calls, but I get different times.
I'm guessing there's some overhead on initial method calls or something else caused by a JVM mechanism. Any ideas what could it be?
For example, one sequential search takes around 3300 ms. If I break it into 13 tasks, it takes a total time of 3500ms.
My method looks like this:
private static final int dfs(State state) {
method_calls++;
if(state.isLeaf()){
return 1;
}
State[] children = state.expand();
int result = 0;
for (int i = 0; i < children.length; i++) {
result += dfs(children[i]);
}
return result;
}
Whenever I call it, I do it like this:
for(int i = 0; i < num_tasks; i++){
long start = System.currentTimeMillis();
dfs(tasks[i]);
totalTime += (System.currentTimeMillis() - start);
}
Problem is totalTime increases with num_tasks and I would expect to stay the same because the method_calls variable stays the same.
You should average out the numbers over longer runs. Secondly the precision of currentTimeMillis may not be sufficient, you can try using System.nanoTime().
As in all the programming languages, whenever you call a procedure or a method, you have to push the environment, initialize the new one, execute the programs instructions, return the value on the stack and finally reset the previous environment. It cost a bit! Create a thread cost also more!
I suppose that if you enlarge the researching tree you will have benefit by the parallelization.
Adding system clock time for several threads seems a weird idea. Either you are interested in the time until processing is complete, in which case adding doesn't make sense, or in cpu usage, in which case you should only count when the thread is actually scheduled to execute.
What probably happens is that at least part of the time, more threads are ready to execute than the system has cpu cores, and the scheduler puts one of your threads to sleep, which causes it to take longer to complete. It makes sense that this effect is exacerbated the more threads you use. (Even if your program uses less threads than you have cores, other programs (such as your development environment, ...) might).
If you are interested in CPU usage, you might wish to query ThreadMXBean.getCurrentThreadCpuTime
I'd expect to see Threads used. Something like this:
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Puzzle {
static volatile long totalTime = 0;
private static int method_calls = 0;
/**
* #param args
*/
public static void main(String[] args) {
final int num_tasks = 13;
final State[] tasks = new State[num_tasks];
ExecutorService threadPool = Executors.newFixedThreadPool(5);
for(int i = 0; i < num_tasks; i++){
threadPool.submit(new DfsRunner(tasks[i]));
}
try {
threadPool.shutdown();
threadPool.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println(method_calls + " Methods in " + totalTime + "msecs");
}
static final int dfs(State state) {
method_calls++;
if(state.isLeaf()){
return 1;
}
State[] children = state.expand();
int result = 0;
for (int i = 0; i < children.length; i++) {
result += dfs(children[i]);
}
return result;
}
}
With the runnable bit like this:
public class DfsRunner implements Runnable {
private State state;
public DfsRunner(State state) {
super();
this.state = state;
}
#Override
public void run() {
long start = System.currentTimeMillis();
Puzzle.dfs(state);
Puzzle.totalTime += (System.currentTimeMillis() - start);
}
}

Unstable speed of gameloop

I'm making a simple breakout game in OpenGL(-es) on Android. Initially I had the updating of the game's state and the drawing calls in the same loop: onDrawFrame. Now I decided to split up the two, only leaving the rendering calls in onDrawFrame, and the gamestate was managed in another Thread:
public void run() {
Log.d("GameLogicThread", "GameLogicThread started");
final long UPDATE_INTERVAL = 1000000000 / 30;
long endingTime;
int timeElapsed;
long startingTime = System.nanoTime();
while (!running) {// wait for it...
}
while (running) {
endingTime = System.nanoTime();
timeElapsed = (int) (endingTime - startingTime);
Log.d("timeElapsed",Integer.toString(timeElapsed));
if (timeElapsed < UPDATE_INTERVAL-timeElapsed){
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
startingTime = System.nanoTime();
Game.updateGame(timeElapsed);
}
EDIT
I now have changed the code like this ^^, but it still doesn't work correctly..
Is it something in the loop itself that's wrong, or should I look outside (Probably not, since it worked great before moving the code). What should I do?
There are a few logical errors which are pointed out/discussed in the comments below:
endingTime = System.currentTimeMillis();
timeElapsed = (int) (endingTime - startingTime);
// Why is the "elapsed" time being waited? Hmm.
// If *any* wait is being done (I'd recommend sleep(0) for starters)
// it should be the MAXIMUM desired cycle time MINUS the
// currently used cycle time (MINUS some fudge factor).
if (timeElapsed < UPDATE_INTERVAL) // I dislike hanging blocks...
try {
Thread.sleep(timeElapsed);
} catch (InterruptedException e) {
e.printStackTrace();
}
startingTime = System.currentTimeMillis();
// The game needs to know the TOTAL time elapsed since
// the last update, not the time "until before the yield".
// This will likely be passed fictitiously small values as
// it is only time the the LAST updateGame took to run.
Game.updateGame(timeElapsed);
I would never expect to see timeElapsed (passed to updateGame) below say 10ms with sleep(...) and the corrected time calculations.
However, it may not have the required precision (increasing the minimum cycle length to say 1/30 sec, which would result from the fixed math, would make this less important): see Cristian Vrabie's answer for a suggestion on a higher-resolution timer. (There may be some better 3rd-party alternatives designed just for this -- there is in "normal" Java -- I don't program Android ;-)
Happy coding.
The loop doesn't look broken to me. The move to separate threads is definitely a good one or you would have serious problems when the rendering of a frame takes too long.
Have you tried to use nanoTime() for more accuracy?

Categories

Resources