Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (579)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  how deal with time spent per thread?  (Read 2179 times)
0 Members and 1 Guest are viewing this topic.
Offline philfrei
« Posted 2011-05-27 08:23:19 »

I have a GUI and a loosely coupled object running on separate threads.

The JSlider on the GUI uses a ChangeListener to update a volatile variable on the object. The object consults this variable on a very frequent basis in a while loop (44100 times per second on average, as it is in the core of a sound playback routine, and consults once per frame).

Now, if the JVM doesn't switch back and forth very often (I have an old Windows XP, Pentium 4, 3.2 GHz, 3GB RAM, so it it's a simulated rather than a true multicore processing situation) then we have this happening: the volatile variable is updated as many as 10 times perhaps before the other thread is allowed to do anything, and thus the other thread sees a rather large jump because it only gets the last update.

Is there a way to alter the JVM to make it switch threads more often? Or is that a place one should not go? (Is it similar to the way one can tweak Garbage Collection frequency, perhaps?)

I suppose I could try to think in terms of putting the updates in a queue for consumption (so none are skipped). But I'll also have to figure out how to spread them out. Dang. Is this what is normally done in such a situation? I can put more smoothing in the response to the slider, but that makes it rather laggy.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #1 - Posted 2011-05-27 10:06:52 »

Sounds like you've got the wrong solution. What exactly is this variable controlling?

If it's just the visual jump you don't like then interpolate between your old and new values. If you actually need to handle all the values it can take then put each variable change event into a list and process that from the other thread.

Alternatively you can tinker with the thread priorities but that's liable to be tricky and only fix the problem on your machine.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #2 - Posted 2011-05-27 10:55:20 »

The interval at which threads are switched is determined with the OS.

If you want higher granularity, you need to enqueue lots of tiny (!) tasks on the EDT so you can stay on the same thread most of the time. Even then your thread will be swiched every now and then...

You're not on a realtime OS, so you shouldn't make any assumptions on how long the delays are between thread executions.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Roquen
« Reply #3 - Posted 2011-05-27 11:58:05 »

So you're polling?  Polling = bad.  So you have a single producer/single consumer model?
Offline pjt33
« Reply #4 - Posted 2011-05-27 14:00:40 »

You can stick a Thread.yield() in your ChangeListener. But I concur with everyone else who's posted that you're Doing It Wrong™
Offline philfrei
« Reply #5 - Posted 2011-05-27 20:29:41 »

Thanks for the replies! It is very heartening to see this willingness to help out.
Quote
Sounds like you've got the wrong solution. What exactly is this variable controlling?
The goal is to have a "real-time" gui control of the volume of an ongoing sound being played via a SourceDataLine. My AudioSystem does not expose a MASTER_VOLUME or any other controls for SourceDataLines, though it does so for Clips. From what I am reading, this is probably a good thing. The proliferation of controls slows down the processing of SourceDataLines and according to "Killer Game Programming in Java" most were removed in 1.5.

So, I have a "SoundCue" object which exposes a volatile "desiredVolume" instance variable, and has an internal "currentVolume" variable. Both are floats. At the point where we get a buffer of byte data from the AudioInputStream, I iterate through that buffer and multiply the "currentVolume" float (between 0 and 1) to the audio value. Before doing so, I consult the "desiredVolume" and increment the "currentVolume" towards it. I increment once per "frame". This might seem extravagant in an inner loop at a crucial point, but I think operations like filtering are commonly done at this stage and are considerably more involved.
1  
2  
3  
4  
5  
6  
if (currentVolume < desiredVolume)
{
    currentVolume += 0.0001;
} else {
    currentVolume -= 0.0001;
}

If the increment value is large (while remaining small enough so as to not cause clicks), and the updates from the JSlider stream are in effect "collapsed", then there will a staircase effect to the volume changes as the currentVolume races up to meet the desiredVolume. If the increment is small, the changes are smoother but are rather laggy. I am annoyed at the degree of lag I'm getting now and was hoping for a bit more responsiveness.

Okay this window is starting to jump around and there are more helpful suggestions to answer, so I will reply in multiple posts.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline philfrei
« Reply #6 - Posted 2011-05-27 20:40:55 »

Quote
You're not on a realtime OS, so you shouldn't make any assumptions on how long the delays are between thread executions.

Has anyone investigated various OS implementations and timed them? I know in "Killer Game Programming in Java" the author lists some common timings for different OS, for example, my Windows XP supposedly has OS updates at around 15msec.

But the "collapsing" of the JSlider data, I guess I was assuming the rate of JVM thread switching would more closely match the rate at which the ChangeListener events are read. If the JVM chooses to give the ChangeListener, say, enough processing time to read 10 events, then I've made 10 updates to the same variable without any other thread getting the opportunity to read the intermediate values.

I was estimating 10 events because that is how many changes are sometimes listed in a row via printlns in the ChangeListener routine and the sound-processing routine in the other thread. I get what seemed like big chunks from each routine, in turn, via these printlns.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline philfrei
« Reply #7 - Posted 2011-05-27 21:04:38 »

Quote
So you're polling?  Polling = bad.  So you have a single producer/single consumer model?
I'm not sure technically if what I'm doing is "polling". Yes, there is a single producer and a single consumer. I think what I'm doing is called "loose coupling". The AudioCue Object which receives the values from the JSlider does so via a volatile instance variable called "desiredVolume". I originally learned to refer to this as a "push" rather than a "pull," as it is the JSlider that initiates the update, placing the value in the AudioCue's volatile "desiredVolume" variable. I'm guessing a "poll" is similar to a "pull"?

Both Riven and OrangyTang refer to the possibility of enqueuing the data from the JSlider. This might help. I'd have to manage the rate at which the values are consumed at the receiving end. Maybe I'll do something like not update the "desiredVolume" with the queue value until the "currentVolume" has actually reached it. Any lagginess will then be mostly driven by the degree to which the JSlider has control of the JVMs attention, if that amount is greater than the time it takes to process the volume changes (which can be set to happen very quickly).


"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline philfrei
« Reply #8 - Posted 2011-05-27 21:12:42 »

Last reply to the set of replies!

Quote
You can stick a Thread.yield() in your ChangeListener. But I concur with everyone else who's posted that you're Doing It Wrong™

This sounds really intriguing! Since it is the ChangeListener's "hogging" of the JVM that I think is affecting the response, forcing it to relinquish makes good sense as a try. But it could have the side effect of causing a pileup on the EDT. I will try it out.

I'm also considering that maybe the degree of lagging, once I "tune" the receiving end's change increment, is tolerable. I should compare it to the "real-time" responsiveness of my digital audio mixer volume controls. I don't recall noticing a problem there, though.

EDIT: the slider on Sonar6 Homestudio in fact has a bit of a "zippering" artifact. So maybe I can consider that tolerable as I never noticed or cared about it before.  

EDIT#2&3: the inclusion of Thread.yield() in the ChangeListener gives a marked improvement in performance! No signs yet of backup in the EDT. The printlns, though are still very bunched. So, I'm guessing my reliance on println as a way of gauging the JVM switching is probably misguided. Should maybe do something like write to a log instead. (no, I let my perceptions fool me, now it seems pretty similar with or without)

Thanks again to everyone who has pitched in!

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline pjt33
« Reply #9 - Posted 2011-05-27 23:39:09 »

I would consider using a Swing timer to send the audio data. That way you remove the cross-thread communication.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline philfrei
« Reply #10 - Posted 2011-05-28 08:05:58 »

Thanks, again. Am currently just launching a generic Thread and it seems to be working fine. I think I'm good now. I'm not totally happy with the response but it seems acceptable for the purpose of the project I'm working on, where the focus is on presenting the sounds, not the gui.

I'm looking forward to showing off the results in the Showcase before too long, maybe by next week since 95% of Memorial Day weekend is booked. I'm all psyched and ready to program the rest of the night, but I have to be up for a 9-5 shift tomorrow morning! Dangity.


"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (35 views)
2014-04-15 18:08:23

BurntPizza (31 views)
2014-04-15 03:46:01

UprightPath (46 views)
2014-04-14 17:39:50

UprightPath (29 views)
2014-04-14 17:35:47

Porlus (46 views)
2014-04-14 15:48:38

tom_mai78101 (67 views)
2014-04-10 04:04:31

BurntPizza (127 views)
2014-04-08 23:06:04

tom_mai78101 (227 views)
2014-04-05 13:34:39

trollwarrior1 (192 views)
2014-04-04 12:06:45

CJLetsGame (199 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!