We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Rendering in Applet
Page Index Toggle Pages: 1
Rendering in Applet (Read 823 times)
Rendering in Applet
Feb 20th, 2009, 9:42pm
 
Hi,

I've got a program thats drawing an array of about 1000 random letters to the screen, inside the draw loop so you get a rapidly changing letter field. Its basically an expanded version of the 'letters' example.

OK, so - it works perfectly smoothly when I run or present it in the dev environment. However when I export as an applet and run it in a browser, it glitches - it will run fine (albeit a little bit slower) for a few seconds, then the rendering hangs for a split second, then it runs fine again, then hangs...and so on.

It happens in FF (java embedded plugin 0.9.6.4) and safari, on a 2.4 intel macbook with 4gb.

I've tried adding delays, sleeping the thread, and setting a low framerate, but it still glitches.

Any suggestions, info, gratefully received.

All the best,

Mike
Re: Rendering in Applet
Reply #1 - Feb 20th, 2009, 10:58pm
 
I am by no means an expert on how exported applets behave, but it sounds to me like your code does two things of relevance: a) draw at a high frame-rate, and b) use a lot of CPU.  I can't tell whether it also ends up consuming a lot of temporary memory for each frame without seeing the code.

All of that's fine when you're running in the dev environment because the environment can (and probably does) work on your behalf to help make sure that your code gets the CPU and memory resources it needs.

But when you run in the browser, well, all bets are off.  Browsers also have to do god knows how many other things all the time--responding to user events, listening on the network, et cetera.  The browser is responsible for hosting your JVM, and almost certainly runs it with different parameters (available memory, CPU throttling, garbage cleanup frequency) than the dev environment.  So I'm not at all surprised that a high frame rate applet might degrade a bit when running in the browser.

The specific behavior you describe sounds to me like periodic invocation of the JVM's garbage collector, which is a sign that your application repeatedly allocates, uses, and then lets go of, chunks of memory.  This is where I would start investigating.

Try to avoid doing a lot of work in the draw() function, particularly creating objects with new, loading fonts, et cetera.  The reason is that if you create those things as local variables within draw(), they'll go out of scope when draw exits.  The next time Processing calls draw() for you, everything starts fresh.  The memory associated with those local variables is gone, unavailable to you.  Eventually, you'll have used up all the memory available to the JVM, at which point it will run the garbage collector to properly release all the stuff you lost track of.

For example, this draw() leaks 1k of memory on each pass:

void draw()
{
 int[] foo = new int[256]; // ints are 4 bytes, so this is 1k
 for(int i = 0; i < 256; i++) // make a list of random numbers
   foo[i] = random(0, width);

 fill(255);
 stroke(0);
 for(int i = 0; i < 256; i++)
   line(foo[i], 0, foo[i], height);
}

Every time the code hits that "new int[256]", it says "hey, JVM, gimme another 1k!"  When draw() exits, it's lost to the void.  Eventually, the garbage collecter has to intervene to save you from yourself.

This code keeps track of the array so you only ever allocate it once, and your code doesn't trigger the garbage collector:

int[] foo = null;
void draw()
{
 if(foo == null) // the first time through draw(), allocate the array.  Subsequent times, re-use it.
   int[] foo = new int[256]; // ints are 4 bytes, so this is 1k
 for(int i = 0; i < 256; i++) // make a list of random numbers
   foo[i] = random(0, width);

 fill(255);
 stroke(0);
 for(int i = 0; i < 256; i++)
   line(foo[i], 0, foo[i], height);
}
Re: Rendering in Applet
Reply #2 - Feb 21st, 2009, 1:13am
 
cloister,

a little off topic, but concerning your code sample.  I was taught that you should let the gc do it's magic and not worry about memory allocations in Java.  In sample code, I see lots of instances where the same variable is declared in each iteration of a loop.  Seems like a standard Java practice to.

So my question is, should I not depend on the gc?  Should each variable be declared once as much as possible, like in your example?  That could result in a lot of extra globally-scoped vars, which I thought was also bad practice.
Re: Rendering in Applet
Reply #3 - Feb 21st, 2009, 2:06am
 
Scalar variables, like for-loop counters and other simple "int x;" stuff you find all over the place, are allocated on the program stack, not in the general memory heap.  Arrays and objects are (usually) allocated on the heap.

Memory allocated on the stack is naturally reclaimed when a function or method call returns.  Memory allocated in the heap is only reclaimed when the garbage collector runs.

When you allocate something with the 'new' operator, be it an array or object, what you're really doing is creating a _stack_ variable that contains the address of a block of _heap_ memory.  A pointer.

When the function or method returns, the _stack variable_ naturally goes away, but the block of _heap memory_ does not.

I'm sure you can read a whole lot more about the difference between stack memory and heap memory on Wikipedia or something if you want to, but that's the core issue here.

Low-level languages like C and C++ make it your job to take heap memory "off the books," as it were, by using the free() funciton or the 'delete' operator.  But, history shows that programmers are totally untrustworthy about doing that job reliably, so modern "managed code" languages like Java and C# don't give you the ability to free memory yourself.

They have a garbage collector to do that for you.  You can think of the garbage collector like a tax auditor.  Its job is to go through the allocator's books and say "hey, nobody's using that, give it back!"  As it happens, it's a lot of work to audit the allocator's books: for every allocation on the books, the GC has to check whether ANY live variable in the program is still pointing at it.  Consequently, performance would suck if the GC were called after, say, every function return.  The JVM would spend practically all its time cleaning up the garbage, and no time executing your program.

So, the GC only executes "once in a while".  The specific policy for invoking the GC varies from platform to platform, but suffice it to say that every so often, when the heap doesn't have very much free space left, the GC pauses EVERYTHING else in the JVM, does its job, and then lets everybody resume.

That slice of time when the GC is doing its thing is probably the little hiccups you're seeing in your program.

Anyway.  Don't sweat little scalar variables.  They're on the stack, not in the heap, and shouldn't affect the GC's performance.  

But, IMHO, any time you explicitly ask for a block of memory using the 'new' keyword, you should take a moment to ask yourself whether you can and/or should arrange to save and re-use that memory between invocations of the function that needs it.
Re: Rendering in Applet
Reply #4 - Feb 21st, 2009, 7:27am
 
Thanks, thats really interesting about the memory allocation. I'm a bit of an old hand at programming so I tried not to code in any memory leaks - but I shall check and make sure. I think you are probably right that its the GC...
Re: Rendering in Applet
Reply #5 - Feb 21st, 2009, 9:46am
 
Thx. for the explanation.  Makes sense.
Page Index Toggle Pages: 1