Re: [visad] finally solved Visad offscreen mode memory problems

Hi Stuart,

Thanks for pointing this out. I'll take a look at it in more detail
later this week, but initially I do have one comment. Rather than
using interrupts, a slightly cleaner way would be to use monitors with
wait and notifyAll, like the code is already doing. It might take
slightly longer than interrupt in certain cases (I'm not sure), but it
gives you more control over the flow of the code. For example, the
graphics context will always get properly disposed.

-Curtis

On 10/26/07, stuart@xxxxxxxxxxxxxxxxxx <stuart@xxxxxxxxxxxxxxxxxx> wrote:
> I have mostly tried to use visad for offscreen rendering, from servlets in
> web apps. The intention was
>
> DisplayImpl di = new DisplayImplJ2D( "", w, h );
> BufferedImage bi = di.getImage(true);
> di.destroy();
>
> As you would expect, we want the net memory footprint of the above
> sequence to be just the BufferedImage, which we can save to disk or use a
> servlet to serialize to some web client.  Thus the net footprint is then
> zero.  This is vital in a long lived app like a web site.
>
> I have always had problems, frequently exhausting memory.  I should point
> out that I am trying to render some large images, on the order of 6000 x
> 6000, but really that is beside the point, it just makes the outofmemory
> occur earlier.
>
> Finally, after about 3 years of looking at this, I think have a solution.
> It now seems obvious why it was failing at all.
>
> In VisADCanvasJ2D, we have
>
> stop() {
>   renderThread =null;
> }
>
> and
>
> run() {
>   while ( renderThread != null ) {
>     do some work;
>     wait for more work;
> }
>
> The problem is that the stop code is not powerful enough to halt the run
> code.  At any given point in time, the run code (the renderThread) can be
> anywhere in its loop.  If it is in wait, it will stay there forever.  The
> thread is live, thus the canvas it references (the Runnable) is also, and
> so are any BufferedImages we have built.  we cannot GC any of it.
>
>
> We need to raise an interrupt in this thread.  This will get us out of a
> wait call, if the interrupt is posted either before or during the wait.  I
> think the soln is this
>
> volatile boolean done = false;
>
> stop () {
>   done = true;
>   renderThread.interrupt();
>   renderThread.join();
> }
>
> run() {
>   while( !done ) {
>     try {
>       do some work;
>        wait;
>     } catch( InterruptedException ie ) {
>     }
>   }
> }
>
> This makes the calling program , which calls stop via the
> DisplayImpl.destroy(), wait for the renderThread to finish.  We need the
> boolean done, we cannot do this from stop:
>
> renderThread.interrupt();
> renderThread = null;
>
> since the run could get the interrupt, test the renderThread for non null
> and do another wait, all before the stop can set the renderThread to null
> ( i have tested this and seen it occur).
>
> Initially i coded the joining of the calling (application) thread and
> renderThread using a CountdownLatch set to 1, from java.util.concurrent,
> with stop doing a latch.await() and run doing a latch.countDown() as its
> final action, but the thread join seems equivalent to that (anyone??).
>
> One caveat of raising the interrupt on the renderThread is that somewhere
> in the 'do some work' the newly raised interrupt can lead to an abort of
> the work.  But we dont really care, since we have got our image via
> getImage and then called destroy in that order.
>
> I hope this helps anyone trying to use Visad in offscreen mode,
> particularly in webapps.
>
> Comments welcomed.
>
> Stuart
>
>
> _______________________________________________
> visad mailing list
> visad@xxxxxxxxxxxxxxxx
> For list information, to unsubscribe, visit: 
> http://www.unidata.ucar.edu/mailing_lists/
>


  • 2007 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the visad archives: