📄 progressmeter.java
字号:
package it.unimi.dsi.mg4j.util;import it.unimi.dsi.Util;import java.io.PrintStream;/* * MG4J: Managing Gigabytes for Java * * Copyright (C) 2003-2007 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 2.1 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *//** Tunable progress meter. * * <P>This class provides a simple way to display progress information about long-lasting activities. It also * provides some time measurement. * * <P>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. * * <P>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. * * <P>Additionally, by setting the {@linkplain #expectedUpdates(long) expected amount of updates} you * can get some estimations on the completion time. * * <P>After you finished a run of the meter, you can change its attributes and call {@link #start()} again * to measure another activity. * * <P>A typical call sequence to a progress meter is as follows: * <PRE> * ProgressMeter pm = new ProgressMeter(10, "pumpkins"); * pm.start("Smashing pumpkins..."); * ... activity on pumpkins that calls update() on each pumpkin ... * pm.done(); * </PRE> * * <P>A more flexible behaviour can be obtained at the end of the * process by calling {@link #stop()}: * <PRE> * 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 ); * </PRE> * * <P>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. */@Deprecatedpublic 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. * * <P>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 " <samp> done.</samp>" 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -