// // GTMTestTimer.h // // Copyright 2006-2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // #import #import "GTMDefines.h" #import // GTMTestTimer is done in straight inline C to avoid obj-c calling overhead. // It is for doing test timings at very high precision. // Test Timers have standard CoreFoundation Retain/Release rules. // Test Timers are not thread safe. Test Timers do NOT check their arguments // for NULL. You will crash if you pass a NULL argument in. typedef struct GTMTestTimer { mach_timebase_info_data_t time_base_info_; bool running_; uint64_t start_; uint64_t split_; uint64_t elapsed_; NSUInteger iterations_; NSUInteger retainCount_; } GTMTestTimer; // Create a test timer GTM_INLINE GTMTestTimer *GTMTestTimerCreate(void) { GTMTestTimer *t = (GTMTestTimer *)calloc(sizeof(GTMTestTimer), 1); if (t) { if (mach_timebase_info(&t->time_base_info_) == KERN_SUCCESS) { t->retainCount_ = 1; } else { // COV_NF_START free(t); t = NULL; // COV_NF_END } } return t; } // Retain a timer GTM_INLINE void GTMTestTimerRetain(GTMTestTimer *t) { t->retainCount_ += 1; } // Release a timer. When release count hits zero, we free it. GTM_INLINE void GTMTestTimerRelease(GTMTestTimer *t) { t->retainCount_ -= 1; if (t->retainCount_ == 0) { free(t); } } // Starts a timer timing. Specifically starts a new split. If the timer is // currently running, it resets the start time of the current split. GTM_INLINE void GTMTestTimerStart(GTMTestTimer *t) { t->start_ = mach_absolute_time(); t->running_ = true; } // Stops a timer and returns split time (time from last start) in nanoseconds. GTM_INLINE uint64_t GTMTestTimerStop(GTMTestTimer *t) { uint64_t now = mach_absolute_time(); t->running_ = false; ++t->iterations_; t->split_ = now - t->start_; t->elapsed_ += t->split_; t->start_ = 0; return t->split_; } // returns the current timer elapsed time (combined value of all splits, plus // current split if the timer is running) in nanoseconds. GTM_INLINE double GTMTestTimerGetNanoseconds(GTMTestTimer *t) { uint64_t total = t->elapsed_; if (t->running_) { total += mach_absolute_time() - t->start_; } return (double)(total * t->time_base_info_.numer / t->time_base_info_.denom); } // Returns the current timer elapsed time (combined value of all splits, plus // current split if the timer is running) in seconds. GTM_INLINE double GTMTestTimerGetSeconds(GTMTestTimer *t) { return GTMTestTimerGetNanoseconds(t) * 0.000000001; } // Returns the current timer elapsed time (combined value of all splits, plus // current split if the timer is running) in milliseconds. GTM_INLINE double GTMTestTimerGetMilliseconds(GTMTestTimer *t) { return GTMTestTimerGetNanoseconds(t) * 0.000001; } // Returns the current timer elapsed time (combined value of all splits, plus // current split if the timer is running) in microseconds. GTM_INLINE double GTMTestTimerGetMicroseconds(GTMTestTimer *t) { return GTMTestTimerGetNanoseconds(t) * 0.001; } // Returns the number of splits (start-stop) cycles recorded. // GTMTestTimerGetSeconds()/GTMTestTimerGetIterations() gives you an average // of all your splits. GTM_INLINE NSUInteger GTMTestTimerGetIterations(GTMTestTimer *t) { return t->iterations_; } // Returns true if the timer is running. GTM_INLINE bool GTMTestTimerIsRunning(GTMTestTimer *t) { return t->running_; }