Login | Register
My pages Projects Community openCollabNet

Discussions > cvs > CVS update: joist/java/org/joist/util MemorySentinel.java

Project highlights: Architectural Overview

joist
Discussion topic

Back to topic list

CVS update: joist/java/org/joist/util MemorySentinel.java

Author stack
Full name Michael Stack
Date 2000-11-12 12:16:22 PST
Message User: stack
  Date: 00/11/12 12:16:22

  Modified: java/org/joist/util MemorySentinel.java
  Log:
  Print percentage change and memory in megabytes. Easier to read
  
  Revision Changes Path
  1.2 +235 -117 joist/java/org/joist​/util/MemorySentinel​.java
  
  Index: MemorySentinel.java
  ====================​====================​====================​=======
  RCS file: /cvs/joist/java/org/​joist/util/MemorySen​tinel.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MemorySentinel.java 2000/11/11 04:34:49 1.1
  +++ MemorySentinel.java 2000/11/12 20:16:21 1.2
  @@ -45,7 +45,6 @@
    */
   package org.joist.util;
   
  -
   import org.webmacro.util.Log;
   
    
  @@ -57,10 +56,10 @@
    * the way JoistProperties implements the singleton pattern.
    * <p>
    * Set thread to run in daemon mode. The JVM will not wait on its completion
  - * if it's a daemon thread.
  + * if it's a daemon thread. If only JVM threads running in a JVM, it exits.
    *
    * @author <a href="mailto:stack@c​ollab.net">St.Ack​</a>
  - * @version $Id: MemorySentinel.java,v 1.1 2000/11/11 04:34:49 stack Exp $
  + * @version $Id: MemorySentinel.java,v 1.2 2000/11/12 20:16:21 stack Exp $
    * @see JoistProperties
    */
   public class MemorySentinel extends Thread
  @@ -68,89 +67,97 @@
       /** Class version string
        */
       public static final String versionID
  - = "$Id: MemorySentinel.java,v 1.1 2000/11/11 04:34:49 stack Exp $";
  -
  -
  - /** Default sleep period between logging.
  - * One minute in milliseconds.
  - */
  - private final static long DEFAULT_SLEEP = ( ( 1000 ) * ( 60 ) );
  -
  -
  - /** Period to wait between printings of memory usage.
  - * In milliseconds.
  - */
  - private long period = DEFAULT_SLEEP;
  -
  -
  - /** Run in daemon mode.
  - * If daemon mode, we can run for ever and JVM won't wait on our completion
  - * before exiting.
  - */
  - private boolean daemon = Boolean.FALSE.booleanValue( );
  -
  -
  - /** Should we log?
  - */
  - private boolean on = Boolean.FALSE.booleanValue( );
  -
  -
  - /** Keep here the single thisInstance of this class.
  - * We only want one of these per heap.
  + = "$Id: MemorySentinel.java,v 1.2 2000/11/12 20:16:21 stack Exp $";
  +
  +
  + /** Default sleep period between logging.
  + * One minute in milliseconds.
  + */
  + private final static long DEFAULT_SLEEP = ( ( 1000 ) * ( 60 ) );
  +
  +
  + /** Period to wait between printings of memory usage.
  + * In milliseconds.
  + */
  + private long period = DEFAULT_SLEEP;
  +
  +
  + /** Run in daemon mode.
  + * If daemon mode, we can run for ever and JVM won't wait on our completion
  + * before exiting.
  + */
  + private boolean daemon = Boolean.FALSE.booleanValue( );
  +
  +
  + /** Should we log?
        */
  + private boolean on = Boolean.FALSE.booleanValue( );
  +
  +
  + /** Keep here the single thisInstance of this class.
  + * We only want one of these per heap.
  + */
       private static MemorySentinel thisInstance = null;
  -
  -
  - /** This thread's name.
  - */
  - private final static String THREAD_NAME = "Memory Sentinel";
  -
  -
  +
  +
  + /** This thread's name.
  + */
  + private final static String THREAD_NAME = "Memory Sentinel";
  +
  +
       /** Logging object.
        */
       private final org.webmacro.util.Log log = new Log( "memory", THREAD_NAME );
  -
  -
  - /** Key to pull whether or not to log.
  - */
  - private final static String ON_KEY = "org.joist.util.memo​rysentinel.on";
  -
  -
  - /** Key to pull period between loggings
  - */
  - private final static String PERIOD_KEY
  - = "org.joist.util.memo​rysentinel.period";
  -
  -
  - /** Key to pull whether we should run in daemon mode.
  - */
  - private final static String DAEMON_KEY
  +
  +
  + /** Key to pull whether or not to log.
  + */
  + private final static String ON_KEY = "org.joist.util.memo​rysentinel.on";
  +
  +
  + /** Key to pull period between loggings
  + */
  + private final static String PERIOD_KEY
  + = "org.joist.util.memo​rysentinel.period";
  +
  +
  + /** Key to pull whether we should run in daemon mode.
  + */
  + private final static String DAEMON_KEY
           = "org.joist.util.memo​rysentinel.daemon";
  -
  -
  - /** Constructor.
  - * Private. Only want one thisInstance per heap so make this
  - * singleton class. Reads properties using JoistProperties class.
  +
  +
  + /** Bytes in a megabyte define.
  + * Make it a double otherwise we get integer math (no decimals).
  + */
  + private final static double MEGABYTE = ( 1024 * 1024 );
  +
  +
  + /** Constructor.
  + *
  + * Private. Only want one thisInstance per heap so make this
  + * singleton class. Reads properties using JoistProperties class.
        *
        * @exception NullPointerException If we can't get a JoistProperties
        * instance.
        * @exception IllegalArgumentException If the period we get is
        * negative or greater than once every 24 hours.
  - */
  - private MemorySentinel( )
  - throws NullPointerException, IllegalArgumentException
  - {
  - JoistProperties properties = JoistProperties.getInstance( );
  - if( properties == null )
  - throw new NullPointerException( "JoistProperties is null" );
  + */
  + private MemorySentinel( )
  + throws NullPointerException, IllegalArgumentException
  + {
  + JoistProperties properties = JoistProperties.getInstance( );
  + if( properties == null )
  + throw new NullPointerException( "JoistProperties is null" );
               
           Boolean onSetting = new Boolean( properties.getProperty( ON_KEY ) );
  - on = onSetting.booleanValue( );
  + on = onSetting.booleanValue( );
  +
           Boolean daemonSetting
               = new Boolean( properties.getProperty( DAEMON_KEY ) );
           daemon = daemonSetting.booleanValue( );
           
  - period = Long.parseLong( properties.getProperty( PERIOD_KEY ) );
  + period = Long.parseLong( properties.getProperty( PERIOD_KEY ) );
           if( ( period < 0 ) || ( period > ( 1000 * 60 * 60 * 24 ) ) )
               throw new IllegalArgumentException( "Period negative or too big: "
                   + Long.toString( period ) );
  @@ -163,29 +170,30 @@
                       + ( ( daemon )
                           ? Boolean.TRUE.toString( )
                           : Boolean.FALSE.toString( ) )
  - + ", period (in milliseconds): "
  - + Long.toString( period ) );
  - }
  -
  -
  + + ", period between logs: "
  + + Long.toString( period )
  + + " milliseconds.");
  + }
  +
  +
       /** The first call to getInstance starts the memory sentinel thread.
        *
  - * Safe to call multiple times. Only one thisInstance possible per heap.
  - * Reads properties that tell it interval to run at and whether to run
  - * as daemon thread. Same property file may tell us not to start the
  + * Safe to call multiple times. Only one thisInstance possible per heap.
  + * Reads properties that tell it interval to run at and whether to run
  + * as daemon thread. Same property file may tell us not to start the
        * logging thread.
  - *
  + *
        * @return The single thisInstance of this class.
  - *
  - * @exception IllegalThreadStateException
  - * @exception SecurityException
  + *
  + * @exception IllegalThreadStateException
  + * @exception SecurityException
        * @exception NullPointerException If we can't get a JoistProperties
        * instance.
        * @exception IllegalArgumentException If the period we get is
        * negative or greater than once every 24 hours.
        */
       public static MemorySentinel getInstance( )
  - throws IllegalThreadStateException,
  + throws IllegalThreadStateException,
                   SecurityException,
                   NullPointerException,
                   IllegalArgumentException
  @@ -212,49 +220,159 @@
                   }
               }
           }
  -
  +
           return thisInstance;
  + }
  +
  +
  + /** Print total and free memory to webmacro log on an interval.
  + *
  + * Should be no problems w/ synchronization since there is only one
  + * instance of this class per jvm. Do most of the work in the run method
  + * itself for then i do not need class data members to hold values between
  + * sleeps. Can keep it all storage local to this method.
  + *
  + */
  + public void run( )
  + {
  + Runtime runtime = Runtime.getRuntime( );
  + StringBuffer buffer = new StringBuffer( );
  + long total = runtime.totalMemory( ); // Start w/ sensible values
  + long free = runtime.freeMemory( ); // Start w/ sensible values
  + long previousTotal = total;
  + long previousFree = free; // Previous free memory.
  +
  + while( Boolean.TRUE.booleanValue( ) )
  + {
  + previousTotal = total;
  + previousFree = free;
  + total = runtime.totalMemory( );
  + free = runtime.freeMemory( );
  +
  + buffer.setLength( 0 );
  + buffer.append( "Free: " );
  + buffer.append( format( free, previousFree ) );
  + buffer.append( ", Total: " );
  + buffer.append( format( total, previousTotal ) );
  + buffer.append( "." );
  + log.info( buffer.toString( ) );
  +
  + try
  + {
  + sleep( period );
  + }
  +
  + catch( InterruptedException exception )
  + {
  + log.info( exception.toString( ) );
  + break; // Finish
  + }
  + }
  + }
  +
  +
  + /** Format memory for logging.
  + * Conveniance method. Format passed values for logging as follows:
  + * <pre>
  + * MEMORY_IN_BYTES MEMORY_IN_MEGS (+/-DELTA%)
  + * </pre>
  + * @param inMemory Memory in bytes
  + * @param inPreviousMemory Previous memory value in bytes.
  + * @return Formatted string for logging.
  + */
  + private String format( long inMemory, long inPreviousMemory )
  + {
  + StringBuffer buffer = new StringBuffer( Long.toString( inMemory ) );
  + buffer.append( "B " );
  + buffer.append( strMegabytes( inMemory ) );
  + buffer.append( "M (" );
  + buffer.append( strPercentageDelta( inMemory, inPreviousMemory ) );
  + buffer.append( ")" );
  + return buffer.toString( );
       }
  -
  -
  - /** Print total and free memory to webmacro log on an interval.
  - */
  - public void run( )
  - {
  - Runtime runtime = Runtime.getRuntime( );
  - StringBuffer logBuffer = new StringBuffer( );
  -
  - while( Boolean.TRUE.booleanValue( ) )
  - {
  - logBuffer.setLength( 0 );
  - logBuffer.append( "Total: " );
  - logBuffer.append( runtime.totalMemory( ) );
  - logBuffer.append( ", Free: " );
  - logBuffer.append( runtime.freeMemory( ) );
  - log.info( logBuffer.toString( ) );
  -
  - try
  - {
  - sleep( period );
  - }
  -
  - catch( InterruptedException exception )
  - {
  - log.info( exception.toString( ) );
  - break; // Finish
  - }
  - }
  - }
  -
  +
       
  + /** Return the passed in long of bytes as a pretty string of megabytes.
  + * @param inBytes
  + * @return Megabytes as string w/ a precision of two decimal places
  + */
  + private String strMegabytes( long inBytes )
  + {
  + java.math.BigDecimal megs
  + = new java.math.BigDecimal( inBytes / this.MEGABYTE );
  + megs = megs.setScale( 2, java.math.BigDecimal.ROUND_UP );
  +
  + return megs.toString( );
  + }
  +
  +
  + /** Calculate the percentage delta between two values.
  + * Returns result as a string suitable for logging.
  + * Format returned is +/-DELTA%
  + * @param inNew
  + * @param inOld
  + * @return Return difference between the new and old values as a percentage.
  + * @exception java.lang.ArithmeticException
  + */
  + private String strPercentageDelta( long inNew, long inOld )
  + throws java.lang.ArithmeticException
  + {
  + int delta = percentageDelta( inNew, inOld );
  + StringBuffer strBuffer = new StringBuffer( );
  + if( delta > 0 )
  + strBuffer.append( '+' );
  + if( delta != 0 )
  + strBuffer.append( Integer.toString( delta ) );
  + else
  + strBuffer.append( "0" );
  + strBuffer.append( '%' );
  +
  + return strBuffer.toString( );
  + }
  +
  +
  + /** Calculate percentage delta between two values.
  + * @param inNew
  + * @param inOld
  + * @return Return difference between the new and old values as a percentage.
  + * @exception java.lang.ArithmeticException
  + */
  + private int percentageDelta( long inNew, long inOld )
  + throws java.lang.ArithmeticException
  + {
  + double reusedDouble = inNew - inOld;
  + return ( int )( ( reusedDouble / inOld ) * 100 );
  + }
  +
  +
       /** Main method.
  - *
  - * Used to test this class.
  + *
  + * Used to test this class. Supply at least the PERIOD_KEY
  + * and the ON_KEY properties as system properties on the command
  + * line. Here's an example of how to run this main method:
  + * <pre>
  + * % java -cp ./classes:/home/stac​k/software/webmacro/​webmacro.jar -Dorg.joist.util.mem​orysentinel.period=1​000 -Dorg.joist.util.mem​orysentinel.on=true org.joist.util.MemorySentinel
  + * </pre>
        *
        * @param args List of command line arguments. Ignored.
        */
       public static void main( String[] args )
       {
  - getInstance( );
  + JoistProperties properties = JoistProperties.getInstance( );
  + properties.init( System.getProperties( ) );
  + getInstance( );
  +
  + // Just keep allocating memory so i can watch the memory
  + // logging change values
  + //
  + while( Boolean.TRUE.booleanValue( ) )
  + {
  + StringBuffer strBuffer = new StringBuffer( );
  +
  + for( int i = 0; i < 10000; i++ )
  + {
  + strBuffer.append( "xxxxxxxxxxxxxxxxxxx​xxxxxxxxxxxxxxxxxxxx​x" );
  + }
  + }
       }
   }

« Previous message in topic | 1 of 1 | Next message in topic »

Messages

Show all messages in topic

CVS update: joist/java/org/joist/util MemorySentinel.java stack Michael Stack 2000-11-12 12:16:22 PST
Messages per page: