stopwatch.h revision b0ba9854ae1310425d7c09c72c528239a001e7c7
139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania/*
239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * Copyright (C) 2009 The Android Open Source Project
339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * All rights reserved.
439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *
539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * Redistribution and use in source and binary forms, with or without
639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * modification, are permitted provided that the following conditions
739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * are met:
839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *  * Redistributions of source code must retain the above copyright
939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *    notice, this list of conditions and the following disclaimer.
1039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *  * Redistributions in binary form must reproduce the above copyright
1139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *    notice, this list of conditions and the following disclaimer in
1239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *    the documentation and/or other materials provided with the
1339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *    distribution.
1439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania *
1539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania * SUCH DAMAGE.
2739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania */
2839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
2939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#ifndef ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_
3039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#define ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_
3139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
3239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#include <stdlib.h>
3339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#include <stdio.h>
3439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#include <time.h>
3539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
3639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catanianamespace android_test {
3739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
3839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// StopWatch class to collect execution statistics.
3939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
4039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// Once the watch has been created, start and stop can be called to
4139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// capture an event duration.
4239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
4339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// On completion, use 'sprint' to retrieve the data.
4439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
4539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// If StopWatch::setPrintRawMode(true) has been called, the raw
4639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// samples also are printed.
4739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// The print method is thread safe to avoid mixing the result of
4839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// watches on different threads. For processes, use different files
4939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// that you concat after the run.
5039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
5139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// If the time measure is associated with some volume of data, use
5239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// setMbytes, the print method will compute the average throughput
5339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// based on that value.
5439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
5539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// To capture the time accurately and since the runs are not too long,
5639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// we collect the raw start and stop time in an array that get
5739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// processed once all the measurements have been done.
5839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
5939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// Typical Usage:
6039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania// ==============
6139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
6239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  StopWatch watch("my name", 20);
6339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
6439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  for (int i = 0; i < 20; ++i) {
6539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//    watch.start();
6639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//    doMyStuff();
6739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//    watch.stop();
6839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  }
6939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  char buffer[4096];
7039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  char *str = buffer;
7139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  size_t size = sizeof(buffer);
7239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//  watch.sprint(&str, &size);
7339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania//
7439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
7539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Cataniaclass StopWatch {
7639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania  public:
7739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Time of the snapshot and its nature (start of the interval or end of it).
7839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    struct Measurement {
7939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania        struct timespec mTime;
8039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania        bool mIsStart;
8139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    };
8239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    static const size_t kUseDefaultCapacity = 20;
8339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
8439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Create a stop watch. Default capacity == 2 * interval_nb
8539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // @param name To be used when the results are displayed. No
8639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    //             spaces, use _ instead.
8739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // @param capacity Hint about the number of sampless that will be
8839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    //                 measured (1 sample == 1 start + 1 stop). Used
8939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    //                 to size the internal storage, when the capacity
9039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    //                 is reached, it is doubled.
9139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    StopWatch(const char *name, size_t capacity = kUseDefaultCapacity);
9239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    ~StopWatch();
9339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
9439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // A StopWatch instance measures time intervals. Use setDataSize
9539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // if some volume of data is processed during these intervals, to
9639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // get the average throughput (in kbytes/s) printed.
9739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void setDataSize(size_t size_in_bytes) { mSizeKbytes = size_in_bytes / 1000; }
9839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
9939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Starts and stops the timer. The time between the 2 calls is an
10039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // interval whose duration will be reported in sprint.
10139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void start();
10239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void stop();
10339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
10439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Print a summary of the measurement and optionaly the raw data.
10539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // The summary is commented out using a leading '#'.  The raw data
10639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // is a pair (time, duration). The 1st sample is always at time
10739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // '0.0'.
10839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // @param str[inout] On entry points to the begining of a buffer
10939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // where to write the data. On exit points pass the last byte
11039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // written.
11139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // @param size[inout] On entry points to the size of the buffer
11239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // pointed by *str. On exit *size is the amount of free space left
11339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // in the buffer. If there was not enough space the data is truncated
11439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // and a warning is printed.
11539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void sprint(char **str, size_t *size);
11639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
11739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // @return true if at least one interval was timed.
11839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    bool used() const { return mUsed; }
11939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
12039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Affects all the timers. Instructs all the timers to print the
12139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // raw data as well as the summary.
12239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    static void setPrintRawMode(bool printRaw);
12339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
12439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania  private:
12539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void checkCapacity();
12639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    double timespecToDouble(const struct timespec& time);
12739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void printAverageMinMax(char **str, size_t *size);
12839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void printThroughput(char **str, size_t *size);
12939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    // Allocate mDeltas and fill it in. Search for the min and max.
13039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    void processSamples();
13139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
13239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    char *const mName;  // Name of the test.
13339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    struct timespec mStart;
13439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    size_t mNum; // # of intervals == # of start() calls.
13539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    struct Measurement *mData;
13639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    size_t mDataLen;
13739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    size_t mCapacity;
13839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    int mSizeKbytes;
13939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
14039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    bool mAlreadyPrinted;
14139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    bool mPrintRaw;
14239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
14339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    double mDuration;
144b0ba9854ae1310425d7c09c72c528239a001e7c7Xia Wang    double mDeviation;
14539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    double mMinDuration;
14639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    size_t mMinIdx;
14739c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    double mMaxDuration;
14839c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    size_t mMaxIdx;
14939c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    double *mDeltas;
15039c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
15139c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania    bool mUsed;
15239c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania};
15339c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
15439c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania}  // namespace android_test
15539c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania
15639c016f875b793296a121f41de5775b88f6fa1c9Nicolas Catania#endif  // ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_
157