[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference bulova::decw_jan-89_to_nov-90

Title:DECWINDOWS 26-JAN-89 to 29-NOV-90
Notice:See 1639.0 for VMS V5.3 kit; 2043.0 for 5.4 IFT kit
Moderator:STAR::VATNE
Created:Mon Oct 30 1989
Last Modified:Mon Dec 31 1990
Last Successful Update:Fri Jun 06 1997
Number of topics:3726
Total number of notes:19516

949.0. "Memory leak??" by CERN::EJM () Wed Jun 14 1989 12:53

    I have an application that is computing a picture and then drawing it
    to a window.  It is rather simple and for the moment I do all the
    drawing in memory (to a pixmap) and then call XCopyArea to put it in
    the window.  My problem is that if you watch the virtual page count and
    page faults of the drawing process you see them increase without bound
    (well...).  Nothing that I have tried so far purges my virtual address
    space, even XDestroying the window. However, if I do all the drawing to 
    the pixmap and then do one big XCopyArea at the end my troubles are over.
    
    I regret if this questions has be asked/answered allready but I could
    only find minor references to memory problems that don't exactly apply
    to my case.
    
    Does anyone know of a problem with XCopyArea as far as memory goes?? 
    Or for that matter any routine that draws to a window and not a
    pixmap??
    
    Thanks
    
    	John

T.RTitleUserPersonal
Name
DateLines
949.1dropping pixmaps on the floor?PSW::WINALSKICareful with that VAX, EugeneWed Jun 14 1989 18:105
Make sure you're not creating the pixmap afresh every time, and forgetting to
free the old pixmap.

--PSW

949.2pixmaps aren't the problem?CERN::EJMThu Jun 15 1989 08:4114
    Thanks for the suggestion but it doesn't seem to be my problem.  Even
    if I XFree everything and/or XDestroy my window I never seem to recover
    any of my virtual pages.  It doesn't seem to be a pixmap problem
    because as I said before, if I just write to the pixmap everything is
    peachy.  It's only when I do a XCopyArea that it starts using up the
    virtual memory - as if the call itself is requiring memory.  If I do it
    all to the pixmap and then just one call to XCopyArea at the end to put
    up the picture I have no problems but I would like to see the picture
    developing as it goes (it's a Mandelbrot thing, which I know you are
    familiar with).  Thus the problem is with the multiple calls to
    XCopyArea which make me run out of virtual pages.
    
    John

949.3Client or serverDECWIN::FISHERBurns Fisher 381-1466, ZKO3-4/W23Thu Jun 15 1989 10:079
Would you please make it more clear whether the v.pages are increasing for
the server or for the client?  "Drawing process" was ambiguous to me.  It
seems pretty bizzare if it is the client, but that is what I am inferring
from some of what you said.  XCopyArea should not take up any particular
memory on the client side.  (You aren't creating a GC for each CopyArea
without doing XFreeGC are you?)

Burns

949.4clarification - I hope.CERN::EJMFri Jun 16 1989 08:5519
    re .3
    
    To make things perfectly clear, I hope (sorry for previous ambiguity),
    I declare at the beginning one GC, one Pixmap and one Image.  No other
    pixmaps, gc's or imgages are ever created or destroyed for that matter.
    The virtual pages are increasing on the client - I have looked at the
    server process and notice no unusual behavior.  I didn't mention before
    that I was using an Image with XPutPixel and XGetPixel to refer to what
    I have already drawn because I think I see the virtual pages increasing
    just as a result of the drawing, but I may be mistaken.  Also, as
    mentioned before doing an XFree on any or all of the above pixmaps or
    images doesn't return any virtual memory back to my process.  Only
    upon image exit does this happen.
    
    If it may help, I only have an 8meg machine - 3000 cpu. running VMS
    5.2-42N
    
    -John

949.5PSW::WINALSKICareful with that VAX, EugeneFri Jun 16 1989 20:464
Could you post a code fragment?

--PSW

949.6GraphicsExposures and NoExpose?DECWIN::FISHERBurns Fisher 381-1466, ZKO3-4/W23Mon Jun 19 1989 12:4511
I just had a flash.  I wonder if you are getting back NoExpose or
GraphicsExpose events from the CopyArea and not reading them.  That
could cause XLib to allocate memory to buffer them up in.

You can disable graphics exposures in the GC (this is different from
expose events that come when you pop a window).  You should also
be reading events and dealing with them relatively frequently.  You
can't just let them pile up.

Burns

949.7That was it! (For ME at least)KASINO::TALLETTWindow mangler...Tue Jun 20 1989 11:4513
    Great! That was MY problem at least! I had been chasing an
    apparent memory leak and hadn't realised that even if you
    don't select any events for a window, you always get a (stupid)
    NoExpose event every time you do a XCopyArea or XCopyPlane, even
    from a pixmap (which can never be occluded). You have to actively
    set gc_val.graphics_exposures = False and create your GC with the
    flag GCGraphicsExposures to not get these events!
    
    Thanks guys!
    
    Paul Tallett (Who happened across this note whilst suffering exactly
    		  the same problem).

949.8thanks and code for kicksCERN::EJMSun Jun 25 1989 06:44608
    Very interesting.  This could well be the problem.  I haven't looked
    into this before.  I do read events frequently and I seem to get alot
    of events that don't fit any of the catagories that I'm looking for,
    but I haven't gone so far as to see what they are.  Anyway, I'm posting
    some code for kicks.  I have since sidestepped the problem by no
    calling XCopyArea until the my last level of recursion.  Thus I only
    get around 50 calls per run versus 1000's before.  I will have to see
    about this expose business though.  
    
    Thanks alot.
    
    	John
    
    P.S. Please excuse code sloppiness - still in testing phase.
    
/* This is an attempt to speed up the Mandelbrot drawing by recursively	      */
/* deviding the spaces into areas of all the same color to minimize the	      */
/* number of pixels to calculate.					      */

#include <stdio.h>
#include <math.h>
#include <time.h>

#ifdef VMS
#  include <decw$include:Xlib.h>
#  include <decw$include:Xutil.h>
#else
#  include <X11/Xlib.h>
#  include <X11/Xutil.h>
#endif

#include "mandel.h"

#define SCREEN_SIZE 730

#define REC_LIMIT 1

double xcorner = -2.0, ycorner = 2.0;
double gap = 4.0 / SCREEN_SIZE;
unsigned short current_side;

static XImage *mimage;
static int one_third,	   /* 1/3 the distance of the current block size */
	   two_thirds;	   /* 2 * one_third */

char iter_level = 0, color_changed[6][9][4];

/******************************************************************************/
int get_count( x, y )
/******************************************************************************/
/* calculate and return the count value for complex number at window	      */
/* coordinate (x, y)							      */

double x, y;   /* window coordinate of pixel to calculate		      */

{
register count;
static double z_imag, z_real, z_imag2, z_real2;

   z_imag2 = z_real2 = z_imag = z_real = 0;

   for( count = 0; count < LIMIT; count++ )
   {
      if ( z_real2 + z_imag2 > 4.0 ) return count;

	 z_imag = 2 * z_real * z_imag + y;
	 z_real = z_real2 - z_imag2 + x;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
   }
   return count;
}

/******************************************************************************/
void calc_hline( xwin, ywin, npixels )
/******************************************************************************/
/* calculate and draw a horizontal line starting at window coord (xwin, ywin) */
/* and going for 'npixels'						      */

short xwin, ywin, /* upper-left hand window coord of current block	      */
      npixels;	  /* number of pixels to calculate and draw		      */

{
register n, count;
double c_imag, c_real, z_imag, z_real, z_imag2, z_real2;

   c_imag = ycorner - ywin*gap;

   for ( n = 0; n < npixels; n++ )
   {
      c_real = xcorner + (xwin+n)*gap;
      z_imag2 = z_real2 = z_imag = z_real = 0;

      for( count = 0; count < LIMIT; count++ )
      {
	 if ( z_real2 + z_imag2 > 4.0 ) break;

	 z_imag = 2 * z_real * z_imag + c_imag;
	 z_real = z_real2 - z_imag2 + c_real;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
      }

      XPutPixel( mimage, xwin+n, ywin, color_indices[count-1] );

   }

}

/******************************************************************************/
void calc_vline( xwin, ywin, npixels )
/******************************************************************************/
/* calculate and draw a vertical line starting at window coord (xwin, ywin)   */
/* and going for 'npixels'						      */

short xwin, ywin, /* upper-left hand window coord of current block	      */
      npixels;	  /* number of pixels to calculate and draw		      */

{
register n, count;
double c_imag, c_real, z_imag, z_real, z_imag2, z_real2;

   c_real = xcorner + xwin*gap;

   for ( n = 0; n < npixels; n++ )
   {
      c_imag = ycorner - (ywin+n)*gap;
      z_imag2 = z_real2 = z_imag = z_real = 0;

      for( count = 0; count < LIMIT; count++ )
      {
	 if ( z_real2 + z_imag2 > 4.0 ) break;

	 z_imag = 2 * z_real * z_imag + c_imag;
	 z_real = z_real2 - z_imag2 + c_real;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
      }

      XPutPixel( mimage, xwin, ywin+n, color_indices[count-1] );

   }

}

/******************************************************************************/
void cut_it_up( x, y, side )
/******************************************************************************/
/* divide the block whose upper-left window coord. is (x, y), into a 3 x 3    */
/* matrix of smaller blocks each of side length 'side / 3'		      */
 
short x, y, side;
{

/* calculate and draw horizontal line 1/3 the way down y */

   calc_hline( x+1, y+one_third, side-1 );

/* calculate and draw horizontal line 2/3 the way down y */

   calc_hline( x+1, y+two_thirds, side-1 );


/* calculate and draw vertical line 1/3 the way along x */

   calc_vline( x+one_third, y+1, one_third-1 );

   calc_vline( x+one_third, y+one_third+1, one_third-1 );

   calc_vline( x+one_third, y+two_thirds+1, one_third-1 );


/* calculate and draw vertical line 2/3 the way along x */

   calc_vline( x+two_thirds, y+1, one_third-1 );

   calc_vline( x+two_thirds, y+one_third+1, one_third-1 );

   calc_vline( x+two_thirds, y+two_thirds+1, one_third-1 );

/* last thing has been put in the image so update the pixmap		      */

   XPutImage( main_display, main_pixmap, main_gc, mimage,
	      x, y, x, y, side, side);
/*
   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      x, y, side, side, x, y );
*/
}  
/******************************************************************************/
void check_hline( x, y, npixels, flags )
/******************************************************************************/
/* check a horizontal line of pixels and return flags indication if the	      */
/* color changed in any of its three thirds				      */

short x, y,    /* starting coordinates					      */
      npixels; /* number of pixels to check;				      */
char *flags;   /* pointer to a set of flags indicating color change */

{
char color_changed;
unsigned long color, last_color;
register i;

   color_changed = FALSE;
   last_color = XGetPixel( mimage, x, y );

   for( i = 1; i < npixels; i++ )
   {
      if( (color = XGetPixel( mimage, x+i, y)) != last_color )
	 color_changed = TRUE;

      if( i == one_third )
      {
	 flags[0] = color_changed;
	 color_changed = FALSE;
      }

      if( i == two_thirds )
      {
	 flags[1] = color_changed;
	 color_changed = FALSE;
      }

      last_color = color;
   }

   flags[2] = color_changed;
}
/******************************************************************************/
void check_vline( x, y, npixels, flags )
/******************************************************************************/
/* check a vertical line of pixels and return flags indication if the	      */
/* color changed in any of its three thirds				      */

short x, y,    /* starting coordinates					      */
      npixels; /* number of pixels to check;				      */
char *flags;   /* pointer to a set of flags indicating color change */

{
char color_changed;
unsigned long color, last_color;
register i;

   color_changed = FALSE;
   last_color = XGetPixel( mimage, x, y );

   for( i = 1; i < npixels; i++ )
   {
      if( (color = XGetPixel( mimage, x, y+i)) != last_color )
	 color_changed = TRUE;

      if( i == one_third )
      {
	 flags[0] = color_changed;
	 color_changed = FALSE;
      }

      if( i == two_thirds )
      {
	 flags[1] = color_changed;
	 color_changed = FALSE;
      }

      last_color = color;
   }

   flags[2] = color_changed;
}

/******************************************************************************/
void update_flags( x, y, side )
/******************************************************************************/
/* this routine check the lines that make the exterior of the current block   */
/* who's upper right hand window coordinate is (x,y);  for each line it	      */
/* returns flags indicating if and where it changed color		      */

short x, y,    /* current position in the window */
      side;    /* number of pixels on a side of the current block */
{
char flags[3];

/* check the horizontal lines						      */

   check_hline( x, y, side, flags );		/* top side */
   color_changed[iter_level][0][0] = flags[0];
   color_changed[iter_level][3][0] = flags[1];
   color_changed[iter_level][6][0] = flags[2];

   check_hline( x, y+one_third, side, flags );	/* first third */
   color_changed[iter_level][0][2] = color_changed[iter_level][1][0] = flags[0];
   color_changed[iter_level][3][2] = color_changed[iter_level][4][0] = flags[1];
   color_changed[iter_level][6][2] = color_changed[iter_level][7][0] = flags[2];

   check_hline( x, y+two_thirds, side, flags );	/* second third */
   color_changed[iter_level][1][2] = color_changed[iter_level][2][0] = flags[0];
   color_changed[iter_level][4][2] = color_changed[iter_level][5][0] = flags[1];
   color_changed[iter_level][7][2] = color_changed[iter_level][8][0] = flags[2];

   check_hline( x, y+side, side, flags );	/* bottom side */
   color_changed[iter_level][2][2] = flags[0];
   color_changed[iter_level][5][2] = flags[1];
   color_changed[iter_level][8][2] = flags[2];


/* check the virtical lines						      */

   check_vline( x, y, side, flags );		/* left side */
   color_changed[iter_level][0][3] = flags[0];
   color_changed[iter_level][1][3] = flags[1];
   color_changed[iter_level][2][3] = flags[2];

   check_vline( x+one_third, y, side, flags );	/* first third */
   color_changed[iter_level][0][1] = color_changed[iter_level][3][3] = flags[0];
   color_changed[iter_level][1][1] = color_changed[iter_level][4][3] = flags[1];
   color_changed[iter_level][2][1] = color_changed[iter_level][5][3] = flags[2];

   check_vline( x+two_thirds, y, side, flags );	/* second third */
   color_changed[iter_level][3][1] = color_changed[iter_level][6][3] = flags[0];
   color_changed[iter_level][4][1] = color_changed[iter_level][7][3] = flags[1];
   color_changed[iter_level][5][1] = color_changed[iter_level][8][3] = flags[2];

   check_vline( x+side, y, side, flags );	/* right side */
   color_changed[iter_level][6][1] = flags[0];
   color_changed[iter_level][7][1] = flags[1];
   color_changed[iter_level][8][1] = flags[2];

}
/******************************************************************************/
void fill_by_ones( x, y )
/******************************************************************************/
/* This routine is called when the side of the current block that is being    */
/* calculated is 3, thus making it necessary to fill it in pixel by pixel     */

short x, y;
{
register i, j;
int count;

/* since the outside is already done we only have to fill in the middle four  */
/* pixels								      */

   if( (count = get_count( xcorner+(x+1)*gap, ycorner-(y+1)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+1, y+1 );
   }

   if( (count = get_count( xcorner+(x+2)*gap, ycorner-(y+1)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+2, y+1 );
   }

   if( (count = get_count( xcorner+(x+1)*gap, ycorner-(y+2)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+1, y+2 );
   }

   if( (count = get_count( xcorner+(x+2)*gap, ycorner-(y+2)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+2, y+2 );
   }
}

/******************************************************************************/
void check_blocks( x, y, side )
/******************************************************************************/
/* this is the main engine; for the current block whose upper-left hand	      */
/* window coordinte is (x, y) and length of side is 'side', check to see if   */
/* all the walls of all 9 interior smaller blocks are of the same color	      */
/* if they are then fill in the particular block with that color and move on  */
/* to the next; else cut that block up and start again			      */

short x, y, side;
{
register i, j, block_number;
short newside, newy;
unsigned long color;

   newside = side / 3;
   
   if ( newside > 1 )
   {
      block_number = 0;
      for ( i = 0; i < 3; i++ )
      {
    	 newy = y;
	 for ( j = 0; j < 3; j++, block_number++ )
	 {
	    if( !color_changed[iter_level][block_number][0] &&
		!color_changed[iter_level][block_number][1] &&
	        !color_changed[iter_level][block_number][2] &&
		!color_changed[iter_level][block_number][3] )
	    {
	       if( (color = XGetPixel( mimage, x, newy )) != 0 )
	       {
		  XSetForeground( main_display, main_gc, color );

		  XFillRectangle( main_display, main_pixmap, main_gc,
				  x+1, newy+1, newside-1, newside-1 );
	       }

	       if( iter_level <= 1 )
		  XCopyArea( main_display, main_pixmap, main_window, main_gc,
			     x, newy, newside, newside, x, newy );

	    }
	    else if( newside != 3 )
	    {
	       iter_level++;
	       one_third = newside / 3;
	       two_thirds = 2 * one_third;

	       cut_it_up( x, newy, newside );
	       update_flags( x, newy, newside );
	       check_blocks( x, newy, newside );

	       if( iter_level == 1 )
		  XCopyArea( main_display, main_pixmap, main_window, main_gc,
			     x, newy, newside, newside, x, newy );
	    }
	    else
	       fill_by_ones( x, newy );

	    newy += newside;
	 }
	 x += newside;
      }
   }
   iter_level--;

}

/******************************************************************************/
void createWindow( )
/******************************************************************************/
{

/* Open the display */

   if ( !(main_display = XOpenDisplay( 0 )) ){
      printf( "Can't open display\n" );
      exit( 1 );
   }

/* Create the mask that tells what events to look for in the window */

   main_xswa.save_under = TRUE;

/* set the background and color */

   main_xswa.background_pixel = BlackPixel( main_display,
					    DefaultScreen( main_display ) );

/* create the screen */

   main_screen = XDefaultScreenOfDisplay( main_display );


/* create the window and give it a name */

   main_window =
      XCreateWindow( main_display,     /* display id */

		     XRootWindowOfScreen( main_screen ),  /* window id*/

		     50, 0,	       /* position of upper left hand corner */

		     SCREEN_SIZE, SCREEN_SIZE, /* width and height in pixels */

		     0,		       /* width of border in pixels */

		     XDefaultDepthOfScreen( main_screen ), /* bits per pixel  */

		     InputOutput,      /* type if interaction */

		     XDefaultVisualOfScreen( main_screen ), /* visual struct  */

		     CWBackPixel | CWSaveUnder,  /* attb mask  */

		     &main_xswa);      /* attributes */

   XStoreName( main_display, main_window, "Recursive Mandel " );

   main_gc = XCreateGC( main_display, main_window, 0, 0 );

   XMapWindow( main_display, main_window );

}

/******************************************************************************/
/******************************************************************************/
main(argc, argv)
int argc;
char *argv[];
/******************************************************************************/
/******************************************************************************/
{
int count;
time_t time1, time2, tp;

   createWindow( );

   if ( argc == 1 )
      XSynchronize( main_display, 1 );

   initColors( );


   main_pixmap = XCreatePixmap( main_display, main_window,
				SCREEN_SIZE, SCREEN_SIZE,
				XDefaultDepthOfScreen( main_screen ) );

   XSetForeground( main_display, main_gc, BlackPixelOfScreen( main_screen ) );
   XFillRectangle( main_display, main_pixmap, main_gc,
		   0, 0, SCREEN_SIZE, SCREEN_SIZE );

   mimage = XGetImage( main_display, main_pixmap,
		       0, 0, SCREEN_SIZE, SCREEN_SIZE, AllPlanes, ZPixmap );

/* take a time stamp */

   time1 = time( &tp );
   printf( "%s", ctime( &tp ) );

/* prime the pump by calculating the for corner points */

   if( (count = get_count( -2.0, 2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, 0, 0 );
      XPutPixel( mimage, 0, 0, color_indices[count-1] );
   }


   if( (count = get_count( 2.0, 2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, SCREEN_SIZE-1, 0 );
      XPutPixel( mimage, SCREEN_SIZE-1, 0, color_indices[count-1] );
   }
   

   if( (count = get_count( -2.0, -2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, 0, SCREEN_SIZE-1 );
      XPutPixel( mimage, 0, SCREEN_SIZE-1, color_indices[count-1] );
   }

   if( (count = get_count( 2.0, -2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, SCREEN_SIZE-1, SCREEN_SIZE-1 );
      XPutPixel( mimage, SCREEN_SIZE-1, SCREEN_SIZE-1, color_indices[count-1] );
   }

   one_third = (SCREEN_SIZE-1) / 3;
   two_thirds = 2 * one_third;

/* upper left to upper right */

   calc_hline( 1, 0, SCREEN_SIZE-2 );


/* upper left to lower left */

   calc_vline( 0, 1, SCREEN_SIZE-2 );


/* upper right to lower right */

   calc_vline( SCREEN_SIZE-1, 1, SCREEN_SIZE-2 );


/* lower left to lower right */

   calc_hline( 1, SCREEN_SIZE-1, SCREEN_SIZE-2 );

   cut_it_up( 0, 0, SCREEN_SIZE );
   update_flags( 0, 0, SCREEN_SIZE );
   check_blocks( 0, 0, SCREEN_SIZE-1 );


   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      SCREEN_SIZE-1, 0, 1, SCREEN_SIZE, SCREEN_SIZE-1, 0 );

   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      0, SCREEN_SIZE-1, SCREEN_SIZE, 1, 0, SCREEN_SIZE-1);

   time2 = time( &tp );
   printf( "%s", ctime( &tp ) );
   printf( "#Mins: %f\n", difftime( time2, time1 ) / 60.0 );

   XFlush( main_display );
   printf( "Hit return to end:\007\n" );
   getchar( );

   XFree( mimage );

   WritePixmapFile( main_display, "wholeset.bit", main_pixmap, 0, 0 );

}
    

949.9PSW::WINALSKICareful with that VAX, EugeneMon Jun 26 1989 12:015
The code in .8 does no event processing whatsoever.  Presumably it isn't the
whole program?

--PSW

949.10That's right - butCERN::EJMFri Jun 30 1989 05:167
    True.  This doesn't do any event processing it is spawned by the main
    program and does the calculation and XCopying to the main window. 
    However it is this routing that is increasing in virtual pages, not any
    other.
    
    ejm