Ignore:
Timestamp:
03/18/13 12:12:42 (12 years ago)
Author:
pharms
Message:
  • added a watch for performance measurements
File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/java-utils/src/main/java/de/ugoe/cs/util/StopWatch.java

    r1119 r1128  
    1313//   limitations under the License. 
    1414 
    15 package de.ugoe.cs.autoquest.tasktrees.temporalrelation; 
     15package de.ugoe.cs.util; 
    1616 
    1717import java.io.PrintStream; 
     
    2424/** 
    2525 * <p> 
    26  * TODO comment 
     26 * This is a simple implementation for a stop watch that can be used for performance measures. 
     27 * A stop watch can be used to measure several splits. Each split is started and stopped using the 
     28 * same id provided to the {@link #start(String)} and {@link #stop(String)} methods. The measured 
     29 * durations can be retrieved afterwards using {@link #getDuration(String)}. 
     30 * {@link #dumpStatistics(PrintStream)} is a convenience method useful to effectively dump all 
     31 * information for the different splits. 
    2732 * </p> 
    2833 *  
     
    3237     
    3338    /** 
    34      *  
    35      */ 
    36     private Map<String, List<Long>> mWatches = new HashMap<String, List<Long>>(); 
    37  
    38     /** 
     39     * the splits hold internally 
     40     */ 
     41    private Map<String, Split> mSplits = new HashMap<String, Split>(); 
     42 
     43    /** 
     44     * starts a split with the given id. If the split with the id is already started, an 
     45     * {@link IllegalStateException} is thrown. 
    3946     * 
     47     * @param id the id of the split to be started 
     48     *  
     49     * @throws IllegalStateException if the split is already started 
     50     */ 
     51    public void start(String id) throws IllegalStateException { 
     52        Split split = mSplits.get(id); 
     53         
     54        if (split == null) { 
     55            split = new Split(id); 
     56            mSplits.put(id, split); 
     57        } 
     58         
     59        split.start(); 
     60    } 
     61     
     62    /** 
     63     * stops a split with the given id. If the split with the id is already stopped, an 
     64     * {@link IllegalStateException} is thrown. If no split with the given id exists, an 
     65     * {@link IllegalArgumentException} is thrown. 
    4066     * 
    41      * @param id 
    42      */ 
    43     public void start(String id) { 
    44         List<Long> timeStamps = mWatches.get(id); 
    45          
    46         if (timeStamps == null) { 
    47             timeStamps = new LinkedList<Long>(); 
    48             mWatches.put(id, timeStamps); 
    49         } 
    50          
    51         if (timeStamps.size() % 2 == 0) { 
    52             timeStamps.add(System.currentTimeMillis()); 
    53         } 
    54         else { 
    55             throw new IllegalStateException("watch with id " + id + " already running"); 
    56         } 
    57     } 
    58      
    59     /** 
     67     * @param id the id of the split to be stopped 
     68     *  
     69     * @throws IllegalStateException    if the split is not running 
     70     * @throws IllegalArgumentException if the split with the given id does not exist 
     71     */ 
     72    public void stop(String id) throws IllegalStateException, IllegalArgumentException { 
     73        Split split = mSplits.get(id); 
     74        
     75        if (split == null) { 
     76            throw new IllegalArgumentException("split with id " + id + " does not exist"); 
     77        } 
     78        
     79        split.stop(); 
     80    } 
     81     
     82    /** 
     83     * returns the duration of a split with the given id. If the split with the id is currently 
     84     * running, it is stopped. If no split with the given id exists, an 
     85     * {@link IllegalArgumentException} is thrown. 
    6086     * 
    61      * 
    62      * @param id 
    63      */ 
    64     public void stop(String id) { 
    65         List<Long> timeStamps = mWatches.get(id); 
     87     * @param id the id of the split for which the duration shall be returned 
     88     *  
     89     * @return the duration measured for the split 
     90     *  
     91     * @throws IllegalArgumentException if the split with the given id does not exist 
     92     */ 
     93    public long getDuration(String id) throws IllegalArgumentException { 
     94        Split split = mSplits.get(id); 
     95         
     96        if (split == null) { 
     97            throw new IllegalArgumentException("split with id " + id + " does not exist"); 
     98        } 
    6699        
    67         if (timeStamps == null) { 
    68             throw new IllegalArgumentException("watch with id " + id + " does not exist"); 
    69         } 
    70         
    71         if (timeStamps.size() % 2 == 0) { 
    72             throw new IllegalStateException("watch with id " + id + " already stopped"); 
    73         } 
    74         else { 
    75             timeStamps.add(System.currentTimeMillis()); 
    76         } 
    77     } 
    78      
    79     /** 
    80      * 
    81      * 
    82      * @param id 
    83      */ 
    84     public long getDuration(String id) { 
    85         List<Long> timeStamps = mWatches.get(id); 
    86         
    87         if (timeStamps == null) { 
    88             throw new IllegalArgumentException("watch with id " + id + " does not exist"); 
    89         } 
    90         
    91         if (timeStamps.size() % 2 != 0) { 
    92             stop(id); 
    93         } 
    94          
    95         long result = 0; 
    96         for (long timeStamp : timeStamps) { 
    97             if (result >= 0) { 
    98                 result -= timeStamp; 
    99             } 
    100             else { 
    101                 result += timeStamp; 
    102             } 
    103         } 
    104          
    105         return result; 
    106     } 
    107  
    108     /** 
    109      * 
    110      * @param out 
     100        if (split.isRunning()) { 
     101            split.stop(); 
     102        } 
     103         
     104        return split.getDuration(); 
     105    } 
     106 
     107    /** 
     108     * resets the stop watch and clears all splits  
     109     */ 
     110    public void reset() { 
     111        mSplits.clear(); 
     112    } 
     113     
     114    /** 
     115     * dumps the statistics about the splits. Splits still running are stopped. The method checks 
     116     * if the longest split also covers the other splits. If so, it considers this split as a 
     117     * kind of overall duration and dumps the proportion of all other splits to this split in 
     118     * percentage. 
     119     *  
     120     * @param out the stream to dump the statistics to 
    111121     */ 
    112122    public void dumpStatistics(PrintStream out) { 
    113         if (mWatches.size() <= 0) { 
    114             throw new IllegalStateException("no watches registered that could be dumped"); 
     123        if (mSplits.size() <= 0) { 
     124            throw new IllegalStateException("no splits registered that could be dumped"); 
    115125        } 
    116126         
     
    118128         
    119129        // get durations 
    120         for (String id : mWatches.keySet()) { 
     130        for (String id : mSplits.keySet()) { 
    121131            durations.put(id, getDuration(id)); 
    122132        } 
     
    145155        // get longest duration and check whether it spans all other entries 
    146156        String id = sortedIds.get(sortedIds.size() - 1); 
    147         List<Long> timeStamps = mWatches.get(id); 
    148         long firstTimeStamp = timeStamps.get(0); 
    149         long lastTimeStamp = timeStamps.get(timeStamps.size() - 1); 
    150         long longestDuration = durations.get(id); 
     157        Split longestWatch = mSplits.get(id); 
    151158        boolean longestDurationCoversOthers = true; 
    152159         
    153         for (Map.Entry<String, List<Long>> watch : mWatches.entrySet()) { 
    154             if ((watch.getValue().get(0) < firstTimeStamp) || 
    155                 (watch.getValue().get(watch.getValue().size() - 1) > lastTimeStamp)) 
     160        for (Map.Entry<String, Split> watch : mSplits.entrySet()) { 
     161            if ((watch.getValue().getFirstStart() < longestWatch.getFirstStart()) || 
     162                (watch.getValue().getLastStop() > longestWatch.getLastStop())) 
    156163            { 
    157164                longestDurationCoversOthers = false; 
     
    172179            } 
    173180             
    174             out.print(':'); 
    175             out.print(' '); 
     181            out.print(": "); 
    176182             
    177183            out.print(durations.get(sortedId)); 
    178184            out.print(" ms"); 
    179185             
     186            out.print(" ("); 
     187            out.print(mSplits.get(sortedId).getNoOfStarts()); 
     188            out.print(" starts"); 
     189             
     190            //out.print(", "); 
     191            //out.print(1000 * durations.get(sortedId) / mSplits.get(sortedId).getNoOfStarts()); 
     192            //out.print(" ms per 1000 starts"); 
     193 
    180194            if (longestDurationCoversOthers) { 
    181                 out.print(" ("); 
     195                out.print(", "); 
    182196                out.print(DecimalFormat.getPercentInstance().format 
    183                               ((double) durations.get(sortedId) / longestDuration)); 
    184                 out.print(" of overall duration)"); 
    185             } 
    186             out.println(); 
     197                              ((double) durations.get(sortedId) / longestWatch.getDuration())); 
     198                out.print(" of overall duration"); 
     199            } 
     200             
     201            out.println(')'); 
    187202        } 
    188203         
    189204        out.println(); 
    190205    } 
     206     
     207    /** 
     208     * internally used to store splits 
     209     */ 
     210    private static class Split { 
     211         
     212        /** 
     213         * the id of the split 
     214         */ 
     215        private String id; 
     216         
     217        /** 
     218         * the system time of the first start of the split 
     219         */ 
     220        private long firstStart = -1; 
     221         
     222        /** 
     223         * the system time of the last start of the split 
     224         */ 
     225        private long lastStart = -1; 
     226         
     227        /** 
     228         * the system time of the last stop of the split 
     229         */ 
     230        private long lastStop = -1; 
     231         
     232        /** 
     233         * the duration so far for the split (excluding the time since the last start) 
     234         */ 
     235        private long duration = 0; 
     236         
     237        /** 
     238         * the number of starts or the splits 
     239         */ 
     240        private long noOfStarts = 0; 
     241         
     242        /** 
     243         * initializes the split with its id 
     244         */ 
     245        private Split(String id) { 
     246            this.id = id; 
     247        } 
     248         
     249        /** 
     250         * starts the split if it is not already started 
     251         */ 
     252        private void start() throws IllegalStateException { 
     253            if (lastStart > -1) { 
     254                throw new IllegalStateException("split with id " + id + " already running"); 
     255            } 
     256             
     257            lastStart = System.currentTimeMillis(); 
     258             
     259            if (firstStart < 0) { 
     260                firstStart = lastStart; 
     261            } 
     262             
     263            noOfStarts++; 
     264        } 
     265         
     266        /** 
     267         * checks if the split is currently running 
     268         */ 
     269        private boolean isRunning() { 
     270            return (lastStart > -1); 
     271        } 
     272         
     273        /** 
     274         * stops the split if it is not already stopped 
     275         */ 
     276        private void stop() throws IllegalStateException { 
     277            if (lastStart < 0) { 
     278                throw new IllegalStateException("split with id " + id + " not running"); 
     279            } 
     280             
     281            lastStop = System.currentTimeMillis(); 
     282            duration += lastStop - lastStart; 
     283            lastStart = -1; 
     284        } 
     285         
     286        /** 
     287         * returns the fist start of the split 
     288         */ 
     289        private long getFirstStart() { 
     290            return firstStart; 
     291        } 
     292 
     293        /** 
     294         * returns the last stop of the split 
     295         */ 
     296        private long getLastStop() { 
     297            return lastStop; 
     298        } 
     299 
     300        /** 
     301         * returns the duration of the split measured so far excluding the time since the last  
     302         * start if the split is currently started 
     303         */ 
     304        private long getDuration() { 
     305            return duration; 
     306        } 
     307 
     308        /** 
     309         * returns the number of starts for the split 
     310         */ 
     311        private long getNoOfStarts() { 
     312            return noOfStarts; 
     313        } 
     314    } 
    191315} 
Note: See TracChangeset for help on using the changeset viewer.