Tuesday, 13 July 2010

Java CodeTimer

In the process of writing my first Android application I had the need to time how long a particular section of my code was taking to execute. I couldn't immediately find an obviously available class in the Java or Android utility libraries to help me. So I knocked one up:

import java.text.DecimalFormat;

public class CodeTimer {

    private static final DecimalFormat formatter = new DecimalFormat("###,##0.00");

    private boolean paused = false;
    private long segmentStartNS;
    private long pauseTotalNS = 0;
    private long segmentCount = 0;
    private long minSegmentDeltaNS = Long.MAX_VALUE;
    private long maxSegmentDeltaNS = Long.MIN_VALUE;

    public CodeTimer(boolean startPaused)
    {
        reset(startPaused);
    }

    public void reset(boolean startPaused)
    {
        minSegmentDeltaNS = Long.MAX_VALUE;
        maxSegmentDeltaNS = Long.MIN_VALUE;
        pauseTotalNS = 0;
        segmentCount = 0;
        if ( !startPaused )
            segmentStartNS = System.nanoTime();
        paused = startPaused;
    }

    public void pause()
    {
        if ( paused )
            return;
        long deltaNS = System.nanoTime() - segmentStartNS;
        if ( deltaNS < minsegmentdeltans =" deltaNS;"> maxSegmentDeltaNS )
            maxSegmentDeltaNS = deltaNS;
        pauseTotalNS += deltaNS;
        segmentCount += 1;
        paused = true;
    }

    public void resume()
    {
        if ( !paused )
            return;
        segmentStartNS = System.nanoTime();
        paused = false;
    }

    public String elapsed()
    {
        double deltaMS = elapsedTotalMilliseconds();
        if ( segmentCount > 0 )
        {
            double avgMS = deltaMS / (double)(segmentCount);
            double minMS = ((double)minSegmentDeltaNS) / 1000000.0;
            double maxMS = ((double)maxSegmentDeltaNS) / 1000000.0;
            return formatter.format(deltaMS) + " ms ("
                + segmentCount + " complete sample" + ( (segmentCount>1) ? "s" : "" )
                + ": Avg=" + formatter.format(avgMS)
                + ", Min=" + formatter.format(minMS)
                + ", Max=" + formatter.format(maxMS)
                + ")";
        }
        else
            return formatter.format(deltaMS) + " ms"; // pause has not been used - simple report
    }

    public double elapsedTotalMilliseconds()
    {
        long deltaNS = pauseTotalNS;
        if ( !paused )
            deltaNS += (System.nanoTime() - segmentStartNS);
        return ((double)deltaNS) / 1000000.0;  
    }
 
    public long elapsedTotalMicroseconds()
    {
        return (long)Math.round(elapsedTotalMilliseconds() * 1000.0);
    }

}

The idea is that you instantiate a new instance of this class - optionally telling it whether you want it to time immediately. Then call resume just before the block of code you wish to time and pause just after. Doing this as many times as is necessary. You then use the elapsed method to get a textual description of all timings to far (e.g. to send to the Log.v function).

Hopefully this will help somebody! Please feel free to use this code snippet for your application. No attribution required.

Updated 14 July 2010: In use I noticed a bug in the elapsed method. I've now fixed this plus added two new functions to allow you to query total time passed in milliseconds or microseconds.

1 comments:

  1. I thought your blog could do with a comment - so I claim your comment virginity!

    Found this web article and thought you might appreciate it: http://hackaday.com/2010/07/21/android-development-101-part-3introduction-to-databases/

    ReplyDelete