as an excercise I'm trying to create a metronome with Java using Thread.sleep as a timer and JMF for sounds. It's working out quite well but for some reason JMF seems to be only playing sounds at a maximum of 207 beats per minute.
From my Metronome-class:
public void play() {
soundPlayer.play();
waitPulse();
play();
}
From my SoundPlayer-class:
public void play() {
new Thread(new ThreadPlayer()).start();
}
private class ThreadPlayer implements Runnable {
public void run() {
System.out.println("Click");
player.setMediaTime(new Time(0));
player.start();
}
}
I've made SoundPlayer.play() work as a thread to test if it would make a difference, but it's not. I can easily change tempos up to about 207bpm but even if I set my timer to 1000bpm the sounds aren't played any faster than about 207bpm.
I've put the System.out.println("Click"); inside my ThreadPlayer.run() to check if my loop is working correctly – it is.
The issue seems to be with my implementation of JMF. I'm pretty sure there is a simple solution, can anybody help me out?
Thank you so much for your help! :)
The answer about Thread.sleep() being unreliable is correct: you can't count on it to return in exactly the amount of time you specify. In fact, I'm rather surprised your metronome is usable at all, especially when your system is under load. Read the docs for Thread.sleep() for more details. Max Beikirch's answer about MIDI is a good suggestion: MIDI handles timing very well.
But you ask how to do this with audio. The trick is to open an audio stream and fill it with silence between the metronome clicks and insert the metronome clicks where you want. When you do that, your soundcard plays back the samples (whether they contain a click or silence) at a constant rate. The key here is to keep the audio stream open and never close it. The clock, then, is the audio hardware, not your system clock -- a subtle but important distinction.
So, let's say you are generating 16 bit mono samples at 44100 Hz. Here is a function that will create a click sound at the requested rate. Keep in mind that this click sound is bad for speakers (and your ears) so if you actually use it, play it at a low volume. (Also, this code is untested -- it's just to demonstrate the concept)
int interval = 44100; // 1 beat per second, by default
int count = 0;
void setBPM( float bpm ) {
interval = ( bpm / 60 ) * 44100 ;
}
void generateMetronomeSamples( short[] s ) {
for( int i=0; i<s.length; ++i ) {
s = 0;
++count;
if( count == 0 ) {
s = Short.MAX_VALUE;
}
if( count == interval ) {
count = 0;
}
}
}
Once you set the tempo with setBPM, you can play back the samples generated by calling the the generateMetronomeSamples() function repeatedly, and streaming that output to your speakers using JavaSound. (see JSResources.org for a good tutorial)
Once you have that working, you could replace the harsh click with a sound you get from a WAV or AIFF or a short tone or whatever.
Take your time and take a look at MIDI! - http://www.ibm.com/developerworks/library/it/it-0801art38/ or http://docs.oracle.com/javase/tutorial/sound/TOC.html . It's the best solution for everything related to computer made sound.
My assumption would be, and maybe someone else can jump in here, is that thread running times are up to the whims of the thread scheduler. You can't guaranty how long it will take for the JVM to get back to that thread. Also, seeing as the JVM is running as a process on the machine, and is subject to the OS's process scheduler, you are looking at at least two levels of unpredictability.
Just like Jamie Duby said, just because you tell the Thread to sleep 1 millisecond, doesn't mean that it will get called back at exactly one millisecond. The ONLY guarantee is that AT LEAST one millisecond has passed since you called Thread.sleep();. In reality, the processor cannot process the code fast enough to play a beep sound every millisecond, which is why you see the delay. If you want a dramatic example, make a home-made timer class and try making it count one millisecond for a full minute, you will see that the timer is off by quite a bit.
The person who really deserves the answer credit here is Max Beikrich, Midi is the only way you are going to be able to produce the output you are looking for.
I have far more experience as a musician than a programmer but I just finished a metronome application I started a while back, I had put the project on hold for a while because I couldn't figure out why I was having the same problem you are. Yes Thread.sleep() can be unreliable but I'm managed to make a good metronome using that method.
I saw you mentioned trying an ExecutorService I don't think using concurrent classes will solve your problem. My guess is its a system resource issue, I'm pretty certain MIDIs are the way to go with a metronome. I force my students to practice with a metronome and I've used many, I haven't ever been too concerned with the audio quality of the ticks, timing is far more important and MIDIs are going to be much faster than any other audio file. I used the javax.sound.midi library from the Sound API. I suspect that will solve your problem.
You may notice your ticks are uneven when it works properly, this is due to the Thread.sleep() method not being very reliable. How I solved that problem was by doing all my calculations in nanoseconds using the System.nanoTime() method instead of the System.currentTimeMillis() method, just don't forget to convert back to milliseconds before passing the sleep time into the Thread.sleep() method.
I don't want to post the code for my metronome here in case you want to figure it out on your own but if you'd like to see it just send me an e-mail kevin.bigler3#gmail.com and I'd be happy to send it to you. Good luck.
Related
I am developing a game on android, 'Space RPG' - currently only seeing this error pop up on most Galaxy S4s, and HTC Ones. This is all Java.
The game will stall, when I try to debug the process and suspend the thread in question, it won't suspend, and a spin-on-suspend error happens.
The thread dump lets me see that it was inside a certain while loop that is taking a desired 'end position' and iterating backwards at an ever increasing distance step to find a 'start position'.
This is where things get annoying. I can verify that the loop can not run indefinitely, even though the condition is while(true), it is not possible for it to run more than maybe 200 iterations before my break gets called (this assertion being backed up by the code working on every other phone I have tried).
To help ease my mind on this matter, I added a simple incremented variable inside the loop, and if it ever goes above 1000 it will log something out so I can see that it DID run too many times, just in case some variable was set badly or something.
When this counter code is present, NO crash/hang occurs. Nor do I see any logs indicating it ran over 1000 times.
If I remove this counter, the hang occurs every time after 5-10 seconds of playing [in which the while loop will have run maybe 10 times, though that varies].
My question is therefore, what the hell is going on? :P
Why would these newer phones (but seemingly none of the older phones) have a problem with a loop that is doing valid work and doesn't last long, when there is no incremented variable in there. How could the thread possibly stall in that loop, and how does having an extra counter variable fix the issue?
This work is being done on the opengl render thread, in case that is important.
I have reports of this happening on most S4s, but there is at least one S4 out there where it didn't happen. The one I am using today it IS happening. This makes me wonder if it could possibly be to do with the specific android, java, dalvik or something else on the phone but I unfortunately dont have any details from the S4 where it worked.
Any help, guidance, thoughts or further reading on stuff like this would be appreciated, thanks a lot.
float vel = 1.0f; // final velocity is 1. We are working backwards to find out what the starting velocity will need to be.
int i = 0;
double xmath = Math.sin(rot* (Math.PI/180.0f)); // component of velocity for x,y direction based on rotation
double ymath = Math.cos(rot* (Math.PI/180.0f));
while (true) {
/* with this section uncommented, the stall never happens...
++i;
if (i>1000) {
// Something went rather wrong
vel = 91.0f; // LOG WAS HERE, now has a fallback value justincase
break;
}
*/
vel *= 1.2f;
dx -= vel* xmath;
dy += vel* ymath;
if (distance < (float)Math.sqrt(dx*dx+dy*dy)) {
break;
}
}
// Give the ship a velocity that is appropriate for the distance remaining
_AI.Ship.Velocity = vel;
This is probably http://b.android.com/58726.
The bug has full details; in short: some vendors appear to use a modified version of the Dalvik VM. Changes made to the JIT compiler prevent thread suspension from occurring in certain situations.
The litmus test for this issue is to compare the standard retail device against the "pure Android" Google Play Edition of the GS4 and HTC1. If the former shows the broken behavior, but the latter works correctly, you are likely seeing a vendor-specific problem.
The workaround is to do what you've done: make the code less efficient so it doesn't fall into the "optimized" case. Ideally the app would runtime-select a different code path for devices without the issue, but I don't know of a good way to detect the problem at run time.
Let's say I have a number of sounds (imagine piano/guitar notes).
I want to play each sound after a given interval, for example 200 miliseconds.
But I want to let the previous sound "ring out".
Although the approach below works ok for longer delays (700-1000 ms) it's not too precise.
For short delays, sometimes the sounds "bunch up" and play in rapid succession.
What I tried (sort of pseudo code):
for (Clip clip: clipList){
clip.start();
Thread.sleep(500);
}
My guess this has something to do with thread scheduling by JVM/OS...
Any ideas?
EDIT:
As advised in the comments I tried with a timer too:
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try{
Clip clip = clipList.remove();
clip.start();
}catch (NoSuchElementException e) {
timer.cancel();
}
}
};
timer.schedule(timerTask, 0, delay);
I still get the same behaviour when I have 7-8 sounds and 500 ms delay.
Having the notes "ring out" is a great thing, and something that has driven my researches and trials with Java Sound as well. I'm not sure I can help specifically, but I can share an experience or two.
I made a clip player that allows one to retrigger the clip before it has finished playing (allowing the first to play out while another is started), and at different sample rates. This is done by giving the clip multiple cursors, and having them increment through the internally-stored sample data independently. (The playbacks that are at higher or lower speeds use linear interpolation to derive audio values when the cursor lands in between two samples.) The output is funneled into a single SourceDataLine.
Curiously, when this clip player is invoked multiple times, as a stand-alone program, there is a bunching up that occurs that is similar to what you describe. However, I also wrote an audio mixer that is capable of playing back both a number of these clips AND a sourceDataLine .wav file AND some live FM synth sounds, mixing them all into a SINGLE SourceDataLine output, and the timing on this is pretty darn good!
It really baffles me, as the clip part (and the triggers to the clips) are virtually the same code. One key difference might be that the AudioMixer I wrote is set to run continuously, so some of possible timing problems might be coming from when code is run from bytecode versus from memory. The HotSpot compiler will run code a few times as bytecode before committing to placing it in memory where it will run more quickly, and this would account for some timing problems.
I found a good article on timing issues you might want to check out:
http://quod.lib.umich.edu/cgi/p/pod/dod-idx?c=icmc;idno=bbp2372.2007.131
Basically, java doesn't offer "real time" guarantees, and this is the big challenge to achieving low latency performance. Sources of variance include: the issue of when HotSpot or whatever decides to run from bytecode or from memory, garbage collection, vm thread switching.
Having clips that "play out" would be a key component to doing branching music, allowing one to zig instead of zag at a moment in a game, for example, and the music or sfx would remain "seamless." That is part of what I'm envisioning. Of course, it would also be nice if there was a DAW where one could take a track and designate it be saved as multiple audio tiles (that overlap/playout), rather than making one export each tile individually. But that is getting ahead of the game...Was this a general direction you are also thinking about? Or do you have another application in mind? (Just curious.)
When programming animations and little games I've come to know the incredible importance of Thread.sleep(n); I rely on this method to tell the operating system when my application won't need any CPU, and using this making my program progress in a predictable speed.
My problem is that the JRE uses different methods of implementation of this functionality on different operating systems. On UNIX-based (or influenced) OS:es such as Ubuntu and OS X, the underlying JRE implementation uses a well-functioning and precise system for distributing CPU-time to different applications, and so making my 2D game smooth and lag-free. However, on Windows 7 and older Microsoft systems, the CPU-time distribution seems to work differently, and you usually get back your CPU-time after the given amount of sleep, varying with about 1-2 ms from target sleep. However, you get occasional bursts of extra 10-20 ms of sleep time. This causes my game to lag once every few seconds when this happens. I've noticed this problem exists on most Java games I've tried on Windows, Minecraft being a noticeable example.
Now, I've been looking around on the Internet to find a solution to this problem. I've seen a lot of people using only Thread.yield(); instead of Thread.sleep(n);, which works flawlessly at the cost of the currently used CPU core getting full load, no matter how much CPU your game actually needs. This is not ideal for playing your game on laptops or high energy consumption workstations, and it's an unnecessary trade-off on Macs and Linux systems.
Looking around further I found a commonly used method of correcting sleep time inconsistencies called "spin-sleep", where you only order sleep for 1 ms at a time and check for consistency using the System.nanoTime(); method, which is very accurate even on Microsoft systems. This helps for the normal 1-2 ms of sleep inconsistency, but it won't help against the occasional bursts of +10-20 ms of sleep inconsistency, since this often results in more time spent than one cycle of my loop should take all together.
After tons of looking I found this cryptic article of Andy Malakov, which was very helpful in improving my loop: http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html
Based on his article I wrote this sleep method:
// Variables for calculating optimal sleep time. In nanoseconds (1s = 10^-9ms).
private long timeBefore = 0L;
private long timeSleepEnd, timeLeft;
// The estimated game update rate.
private double timeUpdateRate;
// The time one game loop cycle should take in order to reach the max FPS.
private long timeLoop;
private void sleep() throws InterruptedException {
// Skip first game loop cycle.
if (timeBefore != 0L) {
// Calculate optimal game loop sleep time.
timeLeft = timeLoop - (System.nanoTime() - timeBefore);
// If all necessary calculations took LESS time than given by the sleepTimeBuffer. Max update rate was reached.
if (timeLeft > 0 && isUpdateRateLimited) {
// Determine when to stop sleeping.
timeSleepEnd = System.nanoTime() + timeLeft;
// Sleep, yield or keep the thread busy until there is not time left to sleep.
do {
if (timeLeft > SLEEP_PRECISION) {
Thread.sleep(1); // Sleep for approximately 1 millisecond.
}
else if (timeLeft > SPIN_YIELD_PRECISION) {
Thread.yield(); // Yield the thread.
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
timeLeft = timeSleepEnd - System.nanoTime();
}
while (timeLeft > 0);
}
// Save the calculated update rate.
timeUpdateRate = 1000000000D / (double) (System.nanoTime() - timeBefore);
}
// Starting point for time measurement.
timeBefore = System.nanoTime();
}
SLEEP_PRECISION I usually put to about 2 ms, and SPIN_YIELD_PRECISION to about 10 000 ns for best performance on my Windows 7 machine.
After tons of hard work, this is the absolute best I can come up with. So, since I still care about improving the accuracy of this sleep method, and I'm still not satisfied with the performance, I would like to appeal to all of you java game hackers and animators out there for suggestions on a better solution for the Windows platform. Could I use a platform-specific way on Windows to make it better? I don't care about having a little platform specific code in my applications, as long as the majority of the code is OS independent.
I would also like to know if there is anyone who knows about Microsoft and Oracle working out a better implementation of the Thread.sleep(n); method, or what's Oracle's future plans are on improving their environment as the basis of applications requiring high timing accuracy, such as music software and games?
Thank you all for reading my lengthy question/article. I hope some people might find my research helpful!
You could use a cyclic timer associated with a mutex. This is IHMO the most efficient way of doing what you want. But then you should think about skipping frames in case the computer lags (You can do it with another nonblocking mutex in the timer code.)
Edit: Some pseudo-code to clarify
Timer code:
While(true):
if acquireIfPossible(mutexSkipRender):
release(mutexSkipRender)
release(mutexRender)
Sleep code:
acquire(mutexSkipRender)
acquire(mutexRender)
release(mutexSkipRender)
Starting values:
mutexSkipRender = 1
mutexRender = 0
Edit: corrected initialization values.
The following code work pretty well on windows (loops at exactly 50fps with a precision to the millisecond)
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
final Semaphore mutexRefresh = new Semaphore(0);
final Semaphore mutexRefreshing = new Semaphore(1);
int refresh = 0;
Timer timRefresh = new Timer();
timRefresh.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(mutexRefreshing.tryAcquire()) {
mutexRefreshing.release();
mutexRefresh.release();
}
}
}, 0, 1000/50);
// The timer is started and configured for 50fps
Date startDate = new Date();
while(true) { // Refreshing loop
mutexRefresh.acquire();
mutexRefreshing.acquire();
// Refresh
refresh += 1;
if(refresh % 50 == 0) {
Date endDate = new Date();
System.out.println(String.valueOf(50.0*1000/(endDate.getTime() - startDate.getTime())) + " fps.");
startDate = new Date();
}
mutexRefreshing.release();
}
}
}
Your options are limited, and they depend on what exactly you want to do. Your code snippet mentions the max FPS, but the max FPS would require that you never sleep at all, so I'm not entirely sure what you intend with that. None of that sleep or yield checking is going to make any difference in most of the problem situations however - if some other app needs to run now and the OS doesn't want to switch back soon, it doesn't matter which one of those you call, you'll get control back when the OS decides to do so, which will almost certainly be more than 1ms in the future. However, the OS can certainly be coaxed into making switches more often - Win32 has the timeBeginPeriod call for precisely this purpose, which you may be able to use somehow. But there is a good reason for not switching too often - it's less efficient.
The best thing to do, although somewhat more complex, is usually to go for a game loop that doesn't require real-time updates, but instead performs logic updates at fixed intervals (eg. 20x a second) and renders whenever possible (perhaps with arbitrary short sleeps to free up CPU for other apps, if not running in full-screen). By buffering a past logic state as well as the current one you can interpolate between them to make the rendering appear as smooth as if you were doing logic updates each time. For more information on this approach, you can see the Fix Your Timestep article.
I would also like to know if there is anyone who knows about Microsoft and Oracle working out a better implementation of the Thread.sleep(n); method, or what's Oracle's future plans are on improving their environment as the basis of applications requiring high timing accuracy, such as music software and games?
No, this won't be happening. Remember, sleep is just a method saying how long you want your program to be asleep for. It is not a specification for when it will or should wake up, and never will be. By definition, any system with sleep and yield functionality is a multitasking system, where the requirements of other tasks have to be considered, and the operating system always gets the final call on the scheduling of this. The alternative wouldn't work reliably, because if a program could somehow demand to be reactivated at a precise time of its choosing it could starve other processes of CPU power. (eg. A program that spawned a background thread and had both threads performing 1ms of work and calling sleep(1) at the end could take turns to hog a CPU core.) Thus, for a user-space program, sleep (and functionality like it) will always be a lower bound, never an upper bound. To do better than that requires the OS itself to allow certain apps to pretty much own the scheduling, and this is not a desirable feature in operating systems for consumer hardware (while being a common and useful feature for industrial applications).
Thread.Sleep says you're app needs no more time. This means that in a worst case scenario you'll have to wait for an entire thread slice (40ms or so).
Now in bad cases when a driver or something takes up more time it could be you have to wait for 120ms (3*40ms) so Thread.Sleep is not the way to go. Go another way, like registering a 1ms callback and starting draw code very X callbacks.
(This is on windows, i'd use MultiMedia tools to get those 1ms resolution callbacks)
Timing stuff is notoriously bad on windows. This article is a good place to start. Not sure if you care, but also note that there can be worse problems (especially with System.nanoTime) on virtual systems as well (when windows is the guest operating system).
Thread.sleep is inaccurate and makes the animation jittery most of the time.
If you replace it completely with Thread.yield you'll get a solid FPS without lag or jitter, however the CPU usage increases greatly. I moved to Thread.yield a long time ago.
This problem has been discussed on Java Game Development forums for years.
When programming animations and little games I've come to know the incredible importance of Thread.sleep(n); I rely on this method to tell the operating system when my application won't need any CPU, and using this making my program progress in a predictable speed.
My problem is that the JRE uses different methods of implementation of this functionality on different operating systems. On UNIX-based (or influenced) OS:es such as Ubuntu and OS X, the underlying JRE implementation uses a well-functioning and precise system for distributing CPU-time to different applications, and so making my 2D game smooth and lag-free. However, on Windows 7 and older Microsoft systems, the CPU-time distribution seems to work differently, and you usually get back your CPU-time after the given amount of sleep, varying with about 1-2 ms from target sleep. However, you get occasional bursts of extra 10-20 ms of sleep time. This causes my game to lag once every few seconds when this happens. I've noticed this problem exists on most Java games I've tried on Windows, Minecraft being a noticeable example.
Now, I've been looking around on the Internet to find a solution to this problem. I've seen a lot of people using only Thread.yield(); instead of Thread.sleep(n);, which works flawlessly at the cost of the currently used CPU core getting full load, no matter how much CPU your game actually needs. This is not ideal for playing your game on laptops or high energy consumption workstations, and it's an unnecessary trade-off on Macs and Linux systems.
Looking around further I found a commonly used method of correcting sleep time inconsistencies called "spin-sleep", where you only order sleep for 1 ms at a time and check for consistency using the System.nanoTime(); method, which is very accurate even on Microsoft systems. This helps for the normal 1-2 ms of sleep inconsistency, but it won't help against the occasional bursts of +10-20 ms of sleep inconsistency, since this often results in more time spent than one cycle of my loop should take all together.
After tons of looking I found this cryptic article of Andy Malakov, which was very helpful in improving my loop: http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html
Based on his article I wrote this sleep method:
// Variables for calculating optimal sleep time. In nanoseconds (1s = 10^-9ms).
private long timeBefore = 0L;
private long timeSleepEnd, timeLeft;
// The estimated game update rate.
private double timeUpdateRate;
// The time one game loop cycle should take in order to reach the max FPS.
private long timeLoop;
private void sleep() throws InterruptedException {
// Skip first game loop cycle.
if (timeBefore != 0L) {
// Calculate optimal game loop sleep time.
timeLeft = timeLoop - (System.nanoTime() - timeBefore);
// If all necessary calculations took LESS time than given by the sleepTimeBuffer. Max update rate was reached.
if (timeLeft > 0 && isUpdateRateLimited) {
// Determine when to stop sleeping.
timeSleepEnd = System.nanoTime() + timeLeft;
// Sleep, yield or keep the thread busy until there is not time left to sleep.
do {
if (timeLeft > SLEEP_PRECISION) {
Thread.sleep(1); // Sleep for approximately 1 millisecond.
}
else if (timeLeft > SPIN_YIELD_PRECISION) {
Thread.yield(); // Yield the thread.
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
timeLeft = timeSleepEnd - System.nanoTime();
}
while (timeLeft > 0);
}
// Save the calculated update rate.
timeUpdateRate = 1000000000D / (double) (System.nanoTime() - timeBefore);
}
// Starting point for time measurement.
timeBefore = System.nanoTime();
}
SLEEP_PRECISION I usually put to about 2 ms, and SPIN_YIELD_PRECISION to about 10 000 ns for best performance on my Windows 7 machine.
After tons of hard work, this is the absolute best I can come up with. So, since I still care about improving the accuracy of this sleep method, and I'm still not satisfied with the performance, I would like to appeal to all of you java game hackers and animators out there for suggestions on a better solution for the Windows platform. Could I use a platform-specific way on Windows to make it better? I don't care about having a little platform specific code in my applications, as long as the majority of the code is OS independent.
I would also like to know if there is anyone who knows about Microsoft and Oracle working out a better implementation of the Thread.sleep(n); method, or what's Oracle's future plans are on improving their environment as the basis of applications requiring high timing accuracy, such as music software and games?
Thank you all for reading my lengthy question/article. I hope some people might find my research helpful!
You could use a cyclic timer associated with a mutex. This is IHMO the most efficient way of doing what you want. But then you should think about skipping frames in case the computer lags (You can do it with another nonblocking mutex in the timer code.)
Edit: Some pseudo-code to clarify
Timer code:
While(true):
if acquireIfPossible(mutexSkipRender):
release(mutexSkipRender)
release(mutexRender)
Sleep code:
acquire(mutexSkipRender)
acquire(mutexRender)
release(mutexSkipRender)
Starting values:
mutexSkipRender = 1
mutexRender = 0
Edit: corrected initialization values.
The following code work pretty well on windows (loops at exactly 50fps with a precision to the millisecond)
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
final Semaphore mutexRefresh = new Semaphore(0);
final Semaphore mutexRefreshing = new Semaphore(1);
int refresh = 0;
Timer timRefresh = new Timer();
timRefresh.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(mutexRefreshing.tryAcquire()) {
mutexRefreshing.release();
mutexRefresh.release();
}
}
}, 0, 1000/50);
// The timer is started and configured for 50fps
Date startDate = new Date();
while(true) { // Refreshing loop
mutexRefresh.acquire();
mutexRefreshing.acquire();
// Refresh
refresh += 1;
if(refresh % 50 == 0) {
Date endDate = new Date();
System.out.println(String.valueOf(50.0*1000/(endDate.getTime() - startDate.getTime())) + " fps.");
startDate = new Date();
}
mutexRefreshing.release();
}
}
}
Your options are limited, and they depend on what exactly you want to do. Your code snippet mentions the max FPS, but the max FPS would require that you never sleep at all, so I'm not entirely sure what you intend with that. None of that sleep or yield checking is going to make any difference in most of the problem situations however - if some other app needs to run now and the OS doesn't want to switch back soon, it doesn't matter which one of those you call, you'll get control back when the OS decides to do so, which will almost certainly be more than 1ms in the future. However, the OS can certainly be coaxed into making switches more often - Win32 has the timeBeginPeriod call for precisely this purpose, which you may be able to use somehow. But there is a good reason for not switching too often - it's less efficient.
The best thing to do, although somewhat more complex, is usually to go for a game loop that doesn't require real-time updates, but instead performs logic updates at fixed intervals (eg. 20x a second) and renders whenever possible (perhaps with arbitrary short sleeps to free up CPU for other apps, if not running in full-screen). By buffering a past logic state as well as the current one you can interpolate between them to make the rendering appear as smooth as if you were doing logic updates each time. For more information on this approach, you can see the Fix Your Timestep article.
I would also like to know if there is anyone who knows about Microsoft and Oracle working out a better implementation of the Thread.sleep(n); method, or what's Oracle's future plans are on improving their environment as the basis of applications requiring high timing accuracy, such as music software and games?
No, this won't be happening. Remember, sleep is just a method saying how long you want your program to be asleep for. It is not a specification for when it will or should wake up, and never will be. By definition, any system with sleep and yield functionality is a multitasking system, where the requirements of other tasks have to be considered, and the operating system always gets the final call on the scheduling of this. The alternative wouldn't work reliably, because if a program could somehow demand to be reactivated at a precise time of its choosing it could starve other processes of CPU power. (eg. A program that spawned a background thread and had both threads performing 1ms of work and calling sleep(1) at the end could take turns to hog a CPU core.) Thus, for a user-space program, sleep (and functionality like it) will always be a lower bound, never an upper bound. To do better than that requires the OS itself to allow certain apps to pretty much own the scheduling, and this is not a desirable feature in operating systems for consumer hardware (while being a common and useful feature for industrial applications).
Thread.Sleep says you're app needs no more time. This means that in a worst case scenario you'll have to wait for an entire thread slice (40ms or so).
Now in bad cases when a driver or something takes up more time it could be you have to wait for 120ms (3*40ms) so Thread.Sleep is not the way to go. Go another way, like registering a 1ms callback and starting draw code very X callbacks.
(This is on windows, i'd use MultiMedia tools to get those 1ms resolution callbacks)
Timing stuff is notoriously bad on windows. This article is a good place to start. Not sure if you care, but also note that there can be worse problems (especially with System.nanoTime) on virtual systems as well (when windows is the guest operating system).
Thread.sleep is inaccurate and makes the animation jittery most of the time.
If you replace it completely with Thread.yield you'll get a solid FPS without lag or jitter, however the CPU usage increases greatly. I moved to Thread.yield a long time ago.
This problem has been discussed on Java Game Development forums for years.
I'm writing an AI-testing Framework for a competition. Participants submit a Bot class which matches a given Interface. Then all the bots play a turn-based game. On every turn, I want to do the following:
For every bot B:
start a thread that runs at most N cycles and does B.getNextMove()
wait for all threads to complete
Make all moves (from each bot).
My difficulty comes in saying "at most N cycles". I can limit all the bots by time (say half a second per turn) but this means that some can get more processor cycles than others and doesn't permit a strict "your bot should be able to make its decision re: a turn in X time" requirement in the competition.
As stated, this is in Java. Any ideas? I've been looking at concurrency and locking but this doesn't feel like the right direction. Also, it's possible to not run the bots in Parralel and then use time for the restriction (given that the computer isn't running anything else at the time), but this would be undesirable as it would significantly slow down the speed at which we could have results from the games.
I'd make an interface with the bot to have them do 1 iteration of their algorithm,and do a simple count.
If you need hard time/cpu limits there arn't that many(easy) ways to manage that in java.
You can't measure cpu cycles with java, but you can measure CPU time - which is a vast improvement over using just wall clock time.
To get the cpu time of the current thread you'd use (from the standard java.lang.management package)
ThreadMXBean tm = ManagementFactory.getThreadMXBean();
long cpuTime = tm.getCurrentThreadCpuTime();
Since you're controlling the bot execution and explicitly calling next yourself, why not just count the iterations? e.g.
public class Botcaller extends Thread
{
private Bot bot;
int cycles_completed;
public static final int MAX_ALLOWED_CYCLES=...;
public void run()
{
while (cycles_completed <MAX_ALLOWED_CYCLES)
{
bot.move;
cycles_completed++;
yield()
}
}
}
I think it will be very difficult to control threads at this low a level from Java. I no of know way to stop a thread safely that is running.
Another option is to let each bot run in whatever time it wants. Have one thread per bot but poll the location in a master thread every second. If they haven't updated location in that "round" then they miss out and have to wait for the next one. Make sure that the world state that each bot sees is the one controlled by the master thread.
The nice thing about this approach is that it lets bots sacrifice rounds if they want to do something more complicated.
I think Robocode does something similar... you may want to look there.