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 "time_util.h"
18#include "utilities.h"
19
20#include <cutils/log.h>
21#include <sys/time.h>
22#include <map>
23
24namespace android {
25namespace filterfw {
26
27uint64_t getTimeUs() {
28    static long basesec;
29    struct timeval tv;
30    uint64_t nowtime;
31    gettimeofday(&tv, 0);
32    if (basesec == 0) {
33        basesec = tv.tv_sec;
34    }
35    nowtime = (uint64_t)(tv.tv_sec - basesec) * (uint64_t)1000000 +
36              (uint64_t)tv.tv_usec;
37    return nowtime;
38}
39
40const uint64_t NamedStopWatch::kDefaultLoggingPeriodInFrames = 100;
41
42NamedStopWatch::NamedStopWatch(const std::string& name)
43      : mName(name),
44        mLoggingPeriodInFrames(kDefaultLoggingPeriodInFrames),
45        mStartUSec(0),
46        mNumCalls(0),
47        mTotalUSec(0) {
48}
49
50void NamedStopWatch::Start() {
51    mStartUSec = getTimeUs();
52}
53
54void NamedStopWatch::Stop() {
55    if (!mStartUSec) {
56        return;
57    }
58    uint64_t stopUSec = getTimeUs();
59    if (stopUSec > mStartUSec) {
60        ++mNumCalls;
61        mTotalUSec += stopUSec - mStartUSec;
62        if (mNumCalls % mLoggingPeriodInFrames == 0) {
63            const float mSec = TotalUSec() * 1.0E-3f / NumCalls();
64            ALOGE("%s: %f ms", Name().c_str(), mSec);
65        }
66    }
67    mStartUSec = 0;
68}
69
70namespace {
71static NamedStopWatch* GetWatchForName(const std::string& watch_name) {
72    // TODO: this leaks the NamedStopWatch objects. Replace it with a
73    // singleton to avoid that and make it thread safe.
74    static std::map<std::string, NamedStopWatch*> watches;
75    NamedStopWatch* watch = FindPtrOrNull(watches, watch_name);
76    if (!watch) {
77        watch = new NamedStopWatch(watch_name);
78        watches[watch_name] = watch;
79    }
80    return watch;
81};
82}  // namespace
83
84ScopedTimer::ScopedTimer(const std::string& stop_watch_name) {
85    mWatch = GetWatchForName(stop_watch_name);
86    mWatch->Start();
87}
88
89} // namespace filterfw
90} // namespace android
91