1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "base/logging.h"
18#include "base/utilities.h"
19
20#include "core/time_util.h"
21
22#include <map>
23#include <string>
24#include <sys/time.h>
25
26namespace android {
27namespace filterfw {
28
29uint64_t getTimeUs() {
30    static long basesec;
31    struct timeval tv;
32    uint64_t nowtime;
33    gettimeofday(&tv, 0);
34    if (basesec == 0) {
35        basesec = tv.tv_sec;
36    }
37    nowtime = (uint64_t)(tv.tv_sec - basesec) * (uint64_t)1000000 +
38              (uint64_t)tv.tv_usec;
39    return nowtime;
40}
41
42const uint64_t NamedStopWatch::kDefaultLoggingPeriodInFrames = 100;
43
44NamedStopWatch::NamedStopWatch(const std::string& name)
45      : mName(name),
46        mLoggingPeriodInFrames(kDefaultLoggingPeriodInFrames),
47        mStartUSec(0),
48        mNumCalls(0),
49        mTotalUSec(0) {
50}
51
52void NamedStopWatch::Start() {
53    mStartUSec = getTimeUs();
54}
55
56void NamedStopWatch::Stop() {
57    if (!mStartUSec) {
58        return;
59    }
60    uint64_t stopUSec = getTimeUs();
61    if (stopUSec > mStartUSec) {
62        ++mNumCalls;
63        mTotalUSec += stopUSec - mStartUSec;
64        if (mNumCalls % mLoggingPeriodInFrames == 0) {
65            const float mSec = TotalUSec() * 1.0E-3f / NumCalls();
66            ALOGE("%s: %f ms", Name().c_str(), mSec);
67        }
68    }
69    mStartUSec = 0;
70}
71
72namespace {
73static NamedStopWatch* GetWatchForName(const string& watch_name) {
74    // TODO: this leaks the NamedStopWatch objects. Replace it with a
75    // singleton to avoid that and make it thread safe.
76    static map<string, NamedStopWatch*> watches;
77    NamedStopWatch* watch = FindPtrOrNull(watches, watch_name);
78    if (!watch) {
79        watch = new NamedStopWatch(watch_name);
80        watches[watch_name] = watch;
81    }
82    return watch;
83};
84}  // namespace
85
86ScopedTimer::ScopedTimer(const string& stop_watch_name) {
87    mWatch = GetWatchForName(stop_watch_name);
88    mWatch->Start();
89}
90
91} // namespace filterfw
92} // namespace android
93