summaryrefslogtreecommitdiff
path: root/tests/sdcard/stopwatch.h
blob: 4d1a79491c72d7d085968c84e037a34bb6125849 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (C) 2009 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_
#define ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

namespace android_test {

// StopWatch class to collect execution statistics.
//
// Once the watch has been created, start and stop can be called to
// capture an event duration.
//
// On completion, use 'sprint' to retrieve the data.
//
// If StopWatch::setPrintRawMode(true) has been called, the raw
// samples also are printed.
// The print method is thread safe to avoid mixing the result of
// watches on different threads. For processes, use different files
// that you concat after the run.
//
// If the time measure is associated with some volume of data, use
// setMbytes, the print method will compute the average throughput
// based on that value.
//
// To capture the time accurately and since the runs are not too long,
// we collect the raw start and stop time in an array that get
// processed once all the measurements have been done.
//
// Typical Usage:
// ==============
//
//  StopWatch watch("my name", 20);
//
//  for (int i = 0; i < 20; ++i) {
//    watch.start();
//    doMyStuff();
//    watch.stop();
//  }
//  char buffer[4096];
//  char *str = buffer;
//  size_t size = sizeof(buffer);
//  watch.sprint(&str, &size);
//

class StopWatch {
  public:
    // Time of the snapshot and its nature (start of the interval or end of it).
    struct Measurement {
        struct timespec mTime;
        bool mIsStart;
    };
    static const size_t kUseDefaultCapacity = 20;

    // Create a stop watch. Default capacity == 2 * interval_nb
    // @param name To be used when the results are displayed. No
    //             spaces, use _ instead.
    // @param capacity Hint about the number of sampless that will be
    //                 measured (1 sample == 1 start + 1 stop). Used
    //                 to size the internal storage, when the capacity
    //                 is reached, it is doubled.
    StopWatch(const char *name, size_t capacity = kUseDefaultCapacity);
    ~StopWatch();

    // A StopWatch instance measures time intervals. Use setDataSize
    // if some volume of data is processed during these intervals, to
    // get the average throughput (in kbytes/s) printed.
    void setDataSize(size_t size_in_bytes) { mSizeKbytes = size_in_bytes / 1000; }

    // Starts and stops the timer. The time between the 2 calls is an
    // interval whose duration will be reported in sprint.
    void start();
    void stop();

    // Print a summary of the measurement and optionaly the raw data.
    // The summary is commented out using a leading '#'.  The raw data
    // is a pair (time, duration). The 1st sample is always at time
    // '0.0'.
    // @param str[inout] On entry points to the begining of a buffer
    // where to write the data. On exit points pass the last byte
    // written.
    // @param size[inout] On entry points to the size of the buffer
    // pointed by *str. On exit *size is the amount of free space left
    // in the buffer. If there was not enough space the data is truncated
    // and a warning is printed.
    void sprint(char **str, size_t *size);

    // @return true if at least one interval was timed.
    bool used() const { return mUsed; }

    // Affects all the timers. Instructs all the timers to print the
    // raw data as well as the summary.
    static void setPrintRawMode(bool printRaw);

  private:
    void checkCapacity();
    double timespecToDouble(const struct timespec& time);
    void printAverageMinMax(char **str, size_t *size);
    void printThroughput(char **str, size_t *size);
    // Allocate mDeltas and fill it in. Search for the min and max.
    void processSamples();

    char *const mName;  // Name of the test.
    struct timespec mStart;
    size_t mNum; // # of intervals == # of start() calls.
    struct Measurement *mData;
    size_t mDataLen;
    size_t mCapacity;
    int mSizeKbytes;

    bool mAlreadyPrinted;
    bool mPrintRaw;

    double mDuration;
    double mMinDuration;
    size_t mMinIdx;
    double mMaxDuration;
    size_t mMaxIdx;
    double *mDeltas;

    bool mUsed;
};

}  // namespace android_test

#endif  // ANDROID_NATIVETEST_SYSTEM_EXTRAS_TESTS_SDCARD_STOPWATCH_H_