All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.it.unimi.dsi.big.mg4j.util.ProgressMeter Maven / Gradle / Ivy

Go to download

MG4J (Managing Gigabytes for Java) is a free full-text search engine for large document collections written in Java. The big version is a fork of the original MG4J that can handle more than 2^31 terms and documents.

The newest version!
package it.unimi.dsi.big.mg4j.util;

import it.unimi.dsi.Util;

import java.io.PrintStream;

/*		 
 * MG4J: Managing Gigabytes for Java (big)
 *
 * Copyright (C) 2003-2011 Sebastiano Vigna 
 *
 *  This library is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as published by the Free
 *  Software Foundation; either version 3 of the License, or (at your option)
 *  any later version.
 *
 *  This library is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, see .
 *
 */


/** Tunable progress meter.
 *
 * 

This class provides a simple way to display progress information about long-lasting activities. It also * provides some time measurement. * *

To use this class, you first create a new meter (possibly specifying a {@link java.io.PrintStream} to * receive the {@linkplain #out output}). The output of the meter depends on the quantum (how many calls to {@link #update()} * cause a dot to be printed) and the items name (the name that will be used to denote counted * items). These can be changed at any time with the suitable setters. * *

To measure the progress of an activity, you call {@link #start()} at the beginning, which will * display the quantum. Then, each time you want to mark progress, you call {@link #update()}. When * the activity is over, you call {@link #stop()}. At that point, the method {@link #toString()} returns * information about the internal state of the meter (elapsed time, number of items per second) that * can be printed or otherwise processed. If {@link #update()} has never been called, you will just * get the elapsed time. * *

Additionally, by setting the {@linkplain #expectedUpdates(long) expected amount of updates} you * can get some estimations on the completion time. * *

After you finished a run of the meter, you can change its attributes and call {@link #start()} again * to measure another activity. * *

A typical call sequence to a progress meter is as follows: *

 * ProgressMeter pm = new ProgressMeter(10, "pumpkins");
 * pm.start("Smashing pumpkins...");
 * ... activity on pumpkins that calls update() on each pumpkin ...
 * pm.done();
 * 
* *

A more flexible behaviour can be obtained at the end of the * process by calling {@link #stop()}: *

 * ProgressMeter pm = new ProgressMeter(10, "pumpkins");
 * pm.start("Smashing pumpkins...");
 * ... activity on pumpkins that calls update() on each pumpkin ...
 * pm.stop( " really done!" );
 * System.err.println( pm );
 * 
* *

Note that the output stream of the meter is available via the public field {@link #out}: this * makes it possible to pass around a meter and print additional information on the same stream of the meter. * * @author Sebastiano Vigna * @since 0.6 * @deprecated Use a {@link it.unimi.dsi.logging.ProgressLogger} instead. */ @Deprecated public final class ProgressMeter { /** The time at the last call to {@link #start()}. */ private long start; /** The time at the last call to {@link #stop()}. */ private long stop; /** The number of calls to {@link #update()} since the last {@link #start()}. */ private long count; /** The number of calls to {@link #update()} at the last intermediate speed print. */ private long lastCount; /** The number of expected calls to {@link #update()} (used to compute the percentages, ignored if negative). */ private long expectedUpdates; /** The time at the last intermediate speed print. */ private long last; /** The quantum (number of calls to generate a dot). */ private int quantum; /** The name of several counted items. */ private String itemsName; /** Have we already shown the quantum? */ private boolean shownQuantum; /** The output print stream. It can be used to print information on the same stream used by this progress meter. */ public final java.io.PrintStream out; /** Creates a new progress meter with a quantum equal to one, printing on standard error. */ public ProgressMeter() { this( 1 ); } /** Creates a new progress meter with given quantum, printing on standard error. * * @param quantum the meter quantum. */ public ProgressMeter( final int quantum ) { this( quantum, "items" ); } /** Creates a new progress meter with given quantum, printing on standard error. * * @param quantum the meter quantum. * @param itemsName a plural name denoting the counted items. */ public ProgressMeter( final int quantum, final String itemsName ) { this( quantum, itemsName, System.err ); } /** Creates a new progress meter with given quantum, printing on a given stream. * * @param out a stream that will receive the output of the meter. * @param quantum the meter quantum. * @param itemsName a plural name denoting the counted items. */ public ProgressMeter( final int quantum, final String itemsName, final PrintStream out ) { this.out = out; this.quantum = quantum; this.itemsName = itemsName; this.expectedUpdates = -1; } /** Updates the meter. * *

This call updates the meter internal count. If the count reaches a multiple of the quantum, * a symbol will be printed. */ public void update() { // This method is kept intentionally short so to make it more likely that it is inlined. if ( ++count % quantum != 0 ) return; updateInternal(); } private void updateInternal() { if ( ! shownQuantum && quantum != 1 ) { shownQuantum = true; final double itemsPerSec = count / ( millis() / 1000.0 ); final long millisToEnd = Math.round( ( expectedUpdates - count ) / ( itemsPerSec / 1000.0 ) ); out.print( "[. = " + Util.format( quantum ) + " " + itemsName + ", " + Util.format( itemsPerSec ) + " " + itemsName + "/s" + ( expectedUpdates > 0 ? "; " + Util.format( 100 * count / expectedUpdates ) + "% done, " + millis2hms( millisToEnd ) + " to end" : "" ) + "]" ); } final long n = count / quantum; if ( n % 100 == 0 ) { final long deltaCount = count - lastCount; final long deltaTime = System.currentTimeMillis() - last; final double itemPerSec = ( deltaCount * 1000.0 ) / ( deltaTime + 1 ); final long millisToEnd = Math.round( ( expectedUpdates - count ) / ( itemPerSec / 1000.0 ) ); out.print( "[" + Util.format( count ) + " " + itemsName + ", " + millis2hms( millis() ) + ", " + Util.format( itemPerSec ) + " " + itemsName + "/s" + ( expectedUpdates > 0 ? "; " + Util.format( 100 * count / expectedUpdates ) + "% done, " + millis2hms( millisToEnd ) + " to end" : "" ) + "]" ); lastCount += deltaCount; last += deltaTime; return; } if ( n % 10 == 0 ) { out.print( "+" ); return; } out.print( "." ); return; } /** Sets the quantum. * * @param quantum the new quantum. */ public void quantum( final int quantum ) { this.quantum = quantum; } /** Returns the current quantum. * * @return the current quantum. */ public int quantum() { return quantum; } /** Sets the count. * * @param count the new count. */ public void count( final long count ) { this.count = count; } /** Returns the current count. * * @return the current count. */ public long count() { return count; } /** Sets the expected number of updates. * * @param num the new number. */ public void expectedUpdates( final long num ) { this.expectedUpdates = num; } /** Returns the expected number of updates. * * @return the current expected number of updates. */ public long expectedUpdates() { return expectedUpdates; } /** Sets the items name. * * @param itemsName the new items name. */ public void itemsName( final String itemsName ) { this.itemsName = itemsName; } /** Returns the current items name. * * @return the current items name. */ public String itemsName() { return itemsName; } /** Starts the progress meter, displaying a message and resetting the count. * @param message the message to display. */ public void start( final CharSequence message ) { if ( message != null ) out.print( message ); start = last = System.currentTimeMillis(); lastCount = count = 0; shownQuantum = false; stop = -1; } /** Starts the progress meter, resetting the count. */ public void start() { start( null ); } /** Stops the progress meter, displaying a message terminated by a newline. */ public void stop( final CharSequence message ) { if ( stop != -1 ) return; if ( message != null ) out.println( message ); stop = System.currentTimeMillis(); this.expectedUpdates = -1; } /** Stops the progress meter. */ public void stop() { stop( null ); } /** Completes a run of this progress meter, printing " done." and printing this meter itself. */ public void done() { stop( " done." ); out.println( this ); } /** Returns the number of milliseconds between present time and the last call to {@link #start()}, if * the meter is running, or between the last call to {@link #stop()} and the last call to {@link #start()}, if the * meter is stopped. */ public long millis() { if ( stop != -1 ) return stop - start; else return System.currentTimeMillis() - start; } private String millis2hms( final long t ) { if ( t < 1000 ) return t + "ms"; final long s = ( t / 1000 ) % 60; final long m = ( ( t / 1000 ) / 60 ) % 60; final long h = t / ( 3600 * 1000 ); if ( h == 0 && m == 0 ) return s + "s"; if ( h == 0 ) return m + "m " + s + "s"; return h + "h " + m + "m " + s + "s"; } /** Converts the data stored in this meter to a string. * * @return the data in this meter in a printable form. */ public String toString() { final long t = stop - start + 1 ; if ( t <= 0 ) return "Illegal meter state"; return "Elapsed: " + millis2hms( t ) + ( count != 0 ? " [" + Util.format( count ) + " " + itemsName + ", " + Util.format( count / ( t / 1000.0 ) ) + " " + itemsName + "/s]" : "" ); } } // Local Variables: // mode: jde // tab-width: 4 // End:





© 2015 - 2025 Weber Informatics LLC | Privacy Policy