├── libtimingTests ├── en.lproj │ └── InfoPlist.strings ├── TestAbsoluteTimeConversions.h ├── libtimingTests-Info.plist └── TestAbsoluteTimeConversions.m ├── mathtiming ├── mathtiming-Prefix.pch └── main.m ├── libtiming ├── libtiming-Prefix.pch ├── PRHAbsoluteTimeToNanoseconds.h ├── PRHTimingBlockRecord.h ├── Warnings.xcconfig ├── PRHAbsoluteTimeToNanoseconds.m ├── libtiming.h ├── PRHTimingBlockRecord.m └── libtiming.m ├── LICENSE.txt ├── README.md └── libtiming.xcodeproj └── project.pbxproj /libtimingTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /mathtiming/mathtiming-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'mathtiming' target in the 'mathtiming' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | # import 7 | #endif 8 | -------------------------------------------------------------------------------- /libtiming/libtiming-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'libtiming' target in the 'libtiming' project 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #ifdef __OBJC__ 9 | # import 10 | #endif 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /libtimingTests/TestAbsoluteTimeConversions.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestAbsoluteTimeConversions.h 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-23. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestAbsoluteTimeConversions : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /libtiming/PRHAbsoluteTimeToNanoseconds.h: -------------------------------------------------------------------------------- 1 | // 2 | // PRHAbsoluteTimeToNanoseconds.h 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-23. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | 12 | extern uint64_t PRHAbsoluteTimeToNanoseconds(uint64_t absoluteTime); 13 | extern NSTimeInterval PRHAbsoluteTimeToSeconds(uint64_t absoluteTime); 14 | 15 | extern uint64_t PRHNanosecondsToAbsoluteTime(uint64_t nanoseconds); 16 | extern uint64_t PRHSecondsToAbsoluteTime(NSTimeInterval seconds); 17 | -------------------------------------------------------------------------------- /libtimingTests/libtimingTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.boredzo.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /libtiming/PRHTimingBlockRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // PRHTimingBlockRecord.h 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-22. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import "libtiming.h" 10 | 11 | @interface PRHTimingBlockRecord : NSObject 12 | 13 | @property(copy) dispatch_block_t block; 14 | @property(copy) NSString *name; 15 | 16 | @property(assign) NSUInteger runsExecuted; 17 | - (void) incrementRunsExecuted; 18 | 19 | - (void) run; 20 | 21 | //Called by the timing comparator when this block has been run the maximum number of times. 22 | - (void) markAsCompleted; 23 | 24 | @property(nonatomic, readonly) NSTimeInterval timeTaken; 25 | 26 | @property(copy) PRHTimingReturnBlock returnBlock; 27 | 28 | - (void) startTimingOnQueue:(dispatch_queue_t)queue 29 | minimumNanoseconds:(uint64_t)minimumNanoseconds 30 | minimumRuns:(NSUInteger)minimumRuns 31 | maximumRuns:(NSUInteger)maximumRuns; 32 | - (void) stopTiming; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /libtiming/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | // Warnings.xcconfig 2 | // 3 | // Created by Steven Fisher: 4 | // http://tewha.net/2010/11/xcode-warnings/ 5 | // See also: 6 | // http://boredzo.org/blog/archives/2009-11-07/warnings 7 | // 8 | 9 | 10 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES 11 | GCC_WARN_SHADOW = YES 12 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 13 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES 14 | GCC_WARN_ABOUT_RETURN_TYPE = YES 15 | GCC_WARN_MISSING_PARENTHESES = YES 16 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES 17 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES 18 | GCC_WARN_SIGN_COMPARE = YES 19 | GCC_WARN_UNDECLARED_SELECTOR = YES 20 | GCC_WARN_UNUSED_FUNCTION = YES 21 | GCC_WARN_UNUSED_LABEL = YES 22 | GCC_WARN_UNUSED_VALUE = YES 23 | GCC_WARN_UNUSED_VARIABLE = YES 24 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES 25 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES 26 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES 27 | GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES 28 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES 29 | GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES 30 | GCC_TREAT_WARNINGS_AS_ERRORS = YES 31 | RUN_CLANG_STATIC_ANALYZER = YES 32 | -------------------------------------------------------------------------------- /libtimingTests/TestAbsoluteTimeConversions.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestAbsoluteTimeConversions.m 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-23. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import "TestAbsoluteTimeConversions.h" 10 | 11 | #import "PRHAbsoluteTimeToNanoseconds.h" 12 | @implementation TestAbsoluteTimeConversions 13 | 14 | - (void) testNanosecondsToAbsoluteTimeAndBack { 15 | uint64_t nanoseconds = 40; 16 | uint64_t convertedValue = PRHAbsoluteTimeToNanoseconds(PRHNanosecondsToAbsoluteTime(nanoseconds)); 17 | STAssertEquals(nanoseconds, convertedValue, @"Round trip from nanoseconds (%llu) to absolute time and back returned a wrong number of nanoseconds (%llu)", nanoseconds, convertedValue); 18 | } 19 | - (void) testSecondsToAbsoluteTimeAndBack { 20 | NSTimeInterval seconds = 40.0; 21 | NSTimeInterval convertedValue = PRHAbsoluteTimeToSeconds(PRHSecondsToAbsoluteTime(seconds)); 22 | STAssertEquals(seconds, convertedValue, @"Round trip from seconds (%g) to absolute time and back returned a wrong number of seconds (%g)", seconds, convertedValue); 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /libtiming/PRHAbsoluteTimeToNanoseconds.m: -------------------------------------------------------------------------------- 1 | // 2 | // PRHAbsoluteTimeToNanoseconds.m 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-23. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import "PRHAbsoluteTimeToNanoseconds.h" 10 | 11 | static mach_timebase_info_data_t timebase; 12 | 13 | static void PRHInitTimebase(void) { 14 | static dispatch_once_t onceToken; 15 | dispatch_once(&onceToken, ^{ 16 | mach_timebase_info(&timebase); 17 | }); 18 | } 19 | 20 | uint64_t PRHAbsoluteTimeToNanoseconds(uint64_t absoluteTime) { 21 | return NSEC_PER_SEC * PRHAbsoluteTimeToSeconds(absoluteTime); 22 | } 23 | NSTimeInterval PRHAbsoluteTimeToSeconds(uint64_t absoluteTime) { 24 | PRHInitTimebase(); 25 | 26 | return (absoluteTime * (timebase.numer / (NSTimeInterval)timebase.denom)) / NSEC_PER_SEC; 27 | } 28 | 29 | uint64_t PRHNanosecondsToAbsoluteTime(uint64_t nanoseconds) { 30 | PRHInitTimebase(); 31 | 32 | return nanoseconds / (timebase.numer / (NSTimeInterval)timebase.denom); 33 | } 34 | uint64_t PRHSecondsToAbsoluteTime(NSTimeInterval seconds) { 35 | return PRHNanosecondsToAbsoluteTime(seconds * NSEC_PER_SEC); 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2011 Peter Hosey 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 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. 7 | Neither the name of Peter Hosey nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /mathtiming/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // mathtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-23. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "libtiming.h" 10 | 11 | int main(int argc, char *argv[]) { 12 | @autoreleasepool { 13 | time_t now = time(NULL); 14 | NSUInteger numerator = (now & 0xf); 15 | NSUInteger shiftDistance = 1; 16 | NSUInteger denominator = 1 << shiftDistance; 17 | double numerator_fp = numerator, denominator_fp = denominator; 18 | double multiplier_fp = 1.0 / denominator_fp; 19 | 20 | __block double multiplyResult_fp, divideResult_fp; 21 | __block NSUInteger divideResult, shiftResult; 22 | 23 | PRHTimingComparator *comparator = [PRHTimingComparator new]; 24 | 25 | //PRHTimingComparator supports both style rules. You can have the block first: 26 | [comparator addBlock:^{ 27 | multiplyResult_fp = numerator_fp * multiplier_fp; 28 | } withName:@"Multiply floating-point"]; 29 | [comparator addBlock:^{ 30 | divideResult_fp = numerator_fp / denominator; 31 | } withName:@"Divide floating-point"]; 32 | 33 | //Or the block last: 34 | [comparator addBlockWithName:@"Divide integer" block:^{ 35 | divideResult = numerator / denominator; 36 | }]; 37 | [comparator addBlockWithName:@"Shift integer" block:^{ 38 | shiftResult = numerator >> shiftDistance; 39 | }]; 40 | 41 | comparator.timingFinishedBlock = ^void(bool finishedNormally){ 42 | exit(!finishedNormally); 43 | }; 44 | 45 | [comparator startWithReturnBlock:PRHTimingLogToConsoleReturnBlock]; 46 | 47 | dispatch_main(); 48 | } 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libtiming 2 | 3 | This is a library (currently only a static library) that makes it easy to time multiple implementations of something against each other. 4 | 5 | This basically replaces making a command-line tool for each approach. Instead, you write a single tool that uses this library and wraps each implementation in a block. Add all the blocks to a PRHTimingComparator and start it; it will call a block you give it when each timed block finishes. 6 | 7 | PRHTimingComparator *comparator = [PRHTimingComparator new]; 8 | [comparator addBlockWithName:@"Foo" block:^{ 9 | //Implementation of Foo algorithm 10 | }]; 11 | [comparator addBlockWithName:@"Bar" block:^{ 12 | //Implementation of Bar algorithm 13 | }]; 14 | comparator.timingFinishedBlock = ^void(bool finishedNormally) { 15 | exit(!finishedNormally); 16 | }; 17 | [comparator startWithReturnBlock:PRHTimingLogToConsoleReturnBlock]; 18 | dispatch_main(); 19 | 20 | (`PRHTimingLogToConsoleReturnBlock` is a predefined block that logs a single result to the Console. You can write your own block and use that instead, or in addition.) 21 | 22 | ## Other features 23 | 24 | - There's a minimum number of runs and a minimum amount of time. These are set to default values that will ensure each block is run enough times to generate a meaningful average. 25 | - There's a maximum number of runs and a maximum amount of time. Each block will be run no more than the maximum number of times, and all timing will be aborted at the end of the hard time limit. These are also set to reasonable default values. This will ensure your timing does not take forever. 26 | - Timing is done in parallel, using GCD. 27 | - By default, a comparator uses the default concurrent queue, but you can change it. 28 | 29 | ## What's needed? 30 | 31 | - More test cases. For example: 32 | - It would probably be nice to test that the maximums are truly enforced. 33 | - It would also be good to test it with a serial queue. 34 | -------------------------------------------------------------------------------- /libtiming/libtiming.h: -------------------------------------------------------------------------------- 1 | // 2 | // libtiming.h 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-22. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void (^PRHTimingReturnBlock)(NSString *name, NSUInteger iterations, NSTimeInterval timeTaken, NSTimeInterval timePerIteration); 12 | 13 | //Logs to Console something like “ ran times in seconds ( per iteration)”. 14 | extern PRHTimingReturnBlock PRHTimingLogToConsoleReturnBlock; 15 | 16 | //finishedNormally is true when one of the limits was reached, false when timing was canceled. 17 | typedef void (^PRHTimingFinishedBlock)(bool finishedNormally); 18 | 19 | //You shouldn't rely on these; if you need a specific value, set it yourself. They're defined here in the header as macros so that the values can be both documented and DRY. 20 | #define PRHTimingComparator_DefaultTimeLimit 3 21 | #define PRHTimingComparator_DefaultTimeLimitHeadroomMinutes 5 22 | #define PRHTimingComparator_DefaultTimeLimitHeadroom (PRHTimingComparator_DefaultTimeLimitHeadroomMinutes * 60.0) 23 | #define PRHTimingComparator_DefaultMinimumNumberOfRuns 1.0e+4 24 | #define PRHTimingComparator_DefaultMaximumNumberOfRuns 1.0e+7 25 | 26 | @interface PRHTimingComparator : NSObject 27 | 28 | /*timeLimit and minimumNumberOfRuns are minimums. Each block must run at least that many times, for at least that much time. 29 | *The hard time limit (timeLimit + timeLimitHeadroom) and maximumNumberOfRuns are maximums. Of the two, the hard time limit outranks the maximum number of runs. Each block will be run no more than maximumNumberOfRuns times, and if the hard time limit is reached, timing will come to an end, no matter how many times the blocks have run. 30 | */ 31 | 32 | //Timing will be aborted normally if it goes at least minimumNumberOfRuns times and either takes longer than timeLimit or reaches maximumNumberOfRuns. 33 | @property(assign) NSTimeInterval timeLimit; 34 | //Timing will be forcibly aborted if it goes over time limit + headroom, even if any blocks have not reached the maximum number of runs. 35 | @property(assign) NSTimeInterval timeLimitHeadroom; 36 | //Each block will be run no fewer than this many times (unless the hard time limit is reached). 37 | @property(assign) NSUInteger minimumNumberOfRuns; 38 | //Each block will be run no more than this many times. 39 | @property(assign) NSUInteger maximumNumberOfRuns; 40 | 41 | //Retains using dispatch_retain/dispatch_release. 42 | @property(nonatomic, assign) dispatch_queue_t queue; 43 | 44 | @property(copy) PRHTimingFinishedBlock timingFinishedBlock; 45 | 46 | //The name is your name for the approach that this block takes. 47 | - (void) addBlock:(dispatch_block_t)block withName:(NSString *)name; 48 | //Or, if you prefer the block to come last: 49 | - (void) addBlockWithName:(NSString *)name block:(dispatch_block_t)block; 50 | 51 | //This returns while the blocks are still running. If you want to block until they're all finished, call dispatch_barrier_sync with the comparator's queue. 52 | - (void) startWithReturnBlock:(PRHTimingReturnBlock)returnBlock; 53 | 54 | - (void) cancel; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /libtiming/PRHTimingBlockRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // PRHTimingBlockRecord.m 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-22. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import "PRHTimingBlockRecord.h" 10 | 11 | #import "PRHAbsoluteTimeToNanoseconds.h" 12 | 13 | @implementation PRHTimingBlockRecord 14 | { 15 | dispatch_source_t timerSource, cancelSource; 16 | uint64_t lastRunTime, timeOfCompletion; 17 | uint64_t timeTakenInAbsoluteUnits; 18 | } 19 | 20 | @synthesize block; 21 | @synthesize name; 22 | 23 | @synthesize runsExecuted; 24 | - (void) incrementRunsExecuted { 25 | self.runsExecuted = self.runsExecuted + 1; 26 | } 27 | 28 | @synthesize returnBlock; 29 | 30 | - (void) dealloc { 31 | [self stopTiming]; 32 | } 33 | 34 | - (void) run { 35 | uint64_t start, end; 36 | start = mach_absolute_time(); 37 | self.block(); 38 | end = mach_absolute_time(); 39 | 40 | timeTakenInAbsoluteUnits += end - start; 41 | 42 | lastRunTime = end; 43 | [self incrementRunsExecuted]; 44 | } 45 | 46 | - (void) markAsCompleted { 47 | bool wasRunning = self->timerSource; 48 | [self stopTiming]; 49 | 50 | if (wasRunning) { 51 | timeOfCompletion = lastRunTime; 52 | 53 | NSTimeInterval timeTaken = self.timeTaken; 54 | NSUInteger numberOfRuns = self.runsExecuted; 55 | self.returnBlock(self.name, numberOfRuns, timeTaken, timeTaken / numberOfRuns); 56 | } 57 | } 58 | 59 | - (NSTimeInterval) timeTaken { 60 | return PRHAbsoluteTimeToSeconds(self->timeTakenInAbsoluteUnits); 61 | } 62 | 63 | - (void) startTimingOnQueue:(dispatch_queue_t)queue 64 | minimumNanoseconds:(uint64_t)minimumNanoseconds 65 | minimumRuns:(NSUInteger)minimumRuns 66 | maximumRuns:(NSUInteger)maximumRuns 67 | { 68 | __block PRHTimingBlockRecord *bself = self; 69 | { 70 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, /*handle*/ 0, /*mask*/ 0, queue); 71 | dispatch_source_set_timer(source, DISPATCH_TIME_NOW, /*interval*/ 0, /*leeway*/ 0); 72 | dispatch_source_set_event_handler(source, ^{ 73 | [bself run]; 74 | if (bself->runsExecuted == maximumRuns) 75 | [bself markAsCompleted]; 76 | }); 77 | 78 | self->timerSource = source; 79 | dispatch_resume(self->timerSource); 80 | } 81 | { 82 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, /*handle*/ 0, /*mask*/ 0, queue); 83 | dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, minimumNanoseconds), /*interval*/ minimumNanoseconds, /*leeway*/ 0); 84 | dispatch_source_set_event_handler(source, ^{ 85 | if (bself.runsExecuted < minimumRuns) { 86 | //Keep going. This timer will run again another minimumNanoseconds later. Hopefully we'll have run enough times (or hit a maximum) by then. 87 | } else { 88 | //We have both used (at least) the minimum amount of time and run the minimum number of times. We're done! 89 | [bself markAsCompleted]; 90 | } 91 | }); 92 | 93 | self->cancelSource = source; 94 | dispatch_resume(self->cancelSource); 95 | } 96 | } 97 | - (void) stopTiming { 98 | //Note: This method must be safe to call from our dealloc. 99 | 100 | #define END_SOURCE(source) \ 101 | if (source) { \ 102 | dispatch_source_cancel(source); \ 103 | dispatch_release(source); \ 104 | (source) = nil; \ 105 | } 106 | 107 | END_SOURCE(self->timerSource); 108 | END_SOURCE(self->cancelSource); 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /libtiming/libtiming.m: -------------------------------------------------------------------------------- 1 | // 2 | // libtiming.m 3 | // libtiming 4 | // 5 | // Created by Peter Hosey on 2011-11-22. 6 | // Copyright (c) 2011 Peter Hosey. All rights reserved. 7 | // 8 | 9 | #import "libtiming.h" 10 | 11 | #import "PRHTimingBlockRecord.h" 12 | #import "PRHAbsoluteTimeToNanoseconds.h" 13 | 14 | PRHTimingReturnBlock PRHTimingLogToConsoleReturnBlock = ^(NSString *name, NSUInteger iterations, NSTimeInterval timeTaken, NSTimeInterval timePerIteration) { 15 | NSLog(@"%@ ran %lu times in %f seconds (%f microseconds per iteration)", name, iterations, timeTaken, timePerIteration * USEC_PER_SEC); 16 | }; 17 | 18 | @interface PRHTimingComparator () 19 | @property(strong) NSMutableArray *timingBlockRecords; 20 | @property(nonatomic, assign /*dispatch_retain*/) dispatch_source_t deadlineSource; 21 | @property(assign) bool canceled; 22 | 23 | - (void) finished; 24 | @end 25 | 26 | @implementation PRHTimingComparator 27 | { 28 | uint64_t startTime, softDeadline, totalTimeLimit, endTime; 29 | NSUInteger timingsInProgress; 30 | } 31 | 32 | @synthesize timingBlockRecords; 33 | 34 | @synthesize timeLimit; 35 | @synthesize timeLimitHeadroom; 36 | @synthesize minimumNumberOfRuns; 37 | @synthesize maximumNumberOfRuns; 38 | 39 | @synthesize canceled; 40 | 41 | @synthesize timingFinishedBlock; 42 | 43 | @synthesize queue = _queue; 44 | - (void) setQueue:(dispatch_queue_t)newQueue { 45 | if (self->_queue != newQueue) { 46 | if (self->_queue) 47 | dispatch_release(self->_queue); 48 | 49 | self->_queue = newQueue; 50 | 51 | if (self->_queue) 52 | dispatch_retain(self->_queue); 53 | } 54 | } 55 | 56 | @synthesize deadlineSource = _deadlineSource; 57 | - (void) setDeadlineSource:(dispatch_source_t)newSource { 58 | if (self->_deadlineSource != newSource) { 59 | if (self->_deadlineSource) 60 | dispatch_release(self->_deadlineSource); 61 | 62 | self->_deadlineSource = newSource; 63 | 64 | if (self->_deadlineSource) 65 | dispatch_retain(self->_deadlineSource); 66 | } 67 | } 68 | 69 | - (id) init { 70 | if ((self = [super init])) { 71 | self.timeLimit = PRHTimingComparator_DefaultTimeLimit; 72 | self.timeLimitHeadroom = PRHTimingComparator_DefaultTimeLimitHeadroom; 73 | self.minimumNumberOfRuns = PRHTimingComparator_DefaultMinimumNumberOfRuns; 74 | self.maximumNumberOfRuns = PRHTimingComparator_DefaultMaximumNumberOfRuns; 75 | 76 | self.queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, /*flags*/ 0); 77 | 78 | self.timingBlockRecords = [NSMutableArray new]; 79 | } 80 | return self; 81 | } 82 | 83 | - (void) addBlock:(dispatch_block_t)block withName:(NSString *)name { 84 | PRHTimingBlockRecord *record = [PRHTimingBlockRecord new]; 85 | record.name = name; 86 | record.block = block; 87 | [self.timingBlockRecords addObject:record]; 88 | } 89 | - (void) addBlockWithName:(NSString *)name block:(dispatch_block_t)block { 90 | [self addBlock:block withName:name]; 91 | } 92 | 93 | - (void) startWithReturnBlock:(PRHTimingReturnBlock)returnBlock { 94 | __block PRHTimingComparator *bself = self; 95 | dispatch_queue_t queue = self.queue; 96 | 97 | startTime = mach_absolute_time(); 98 | uint64_t timeLimitInNanoseconds = self.timeLimit * NSEC_PER_SEC; 99 | uint64_t timeLimitInAbsoluteTime = PRHSecondsToAbsoluteTime(self.timeLimit); 100 | softDeadline = startTime + timeLimitInAbsoluteTime; 101 | int64_t timeLimitHeadroomInNanoseconds = (self.timeLimitHeadroom * NSEC_PER_SEC); 102 | uint64_t timeLimitHeadroomInAbsoluteTime = PRHNanosecondsToAbsoluteTime(timeLimitHeadroomInNanoseconds); 103 | totalTimeLimit = timeLimitInAbsoluteTime + timeLimitHeadroomInAbsoluteTime; 104 | 105 | self->timingsInProgress = [self.timingBlockRecords count]; 106 | 107 | NSUInteger minimumRuns = self.minimumNumberOfRuns; 108 | NSUInteger maximumRuns = self.maximumNumberOfRuns; 109 | for (PRHTimingBlockRecord *record in self.timingBlockRecords) { 110 | record.returnBlock = ^void(NSString *name, NSUInteger iterations, NSTimeInterval timeTaken, NSTimeInterval timePerIteration) { 111 | @synchronized(bself) { 112 | if (0 == --bself->timingsInProgress) { 113 | [self finished]; 114 | } 115 | } 116 | returnBlock(name, iterations, timeTaken, timePerIteration); 117 | }; 118 | [record startTimingOnQueue:queue 119 | minimumNanoseconds:timeLimitInNanoseconds 120 | minimumRuns:minimumRuns 121 | maximumRuns:maximumRuns]; 122 | } 123 | 124 | { 125 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, /*handle*/ 0, /*mask*/ 0, queue); 126 | dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, totalTimeLimit), /*interval*/ 0, /*leeway*/ 0); 127 | dispatch_source_set_event_handler(source, ^{ 128 | dispatch_source_cancel(bself.deadlineSource); 129 | }); 130 | dispatch_source_set_cancel_handler(source, ^{ 131 | for (PRHTimingBlockRecord *record in bself.timingBlockRecords) { 132 | //Hard time limit ran out, so tell any records that are still timing to stop now. Each one will also call the return block. 133 | [record markAsCompleted]; 134 | } 135 | 136 | bself.timingFinishedBlock(!(bself.canceled)); 137 | }); 138 | self.deadlineSource = source; 139 | dispatch_release(source); 140 | 141 | dispatch_resume(self.deadlineSource); 142 | } 143 | } 144 | 145 | - (void) finished { 146 | self.canceled = false; 147 | dispatch_source_cancel(self.deadlineSource); 148 | } 149 | - (void) cancel { 150 | self.canceled = true; 151 | dispatch_source_cancel(self.deadlineSource); 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /libtiming.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3109C2D2147DE8190035A276 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD37147CA92A00C6B32F /* Foundation.framework */; }; 11 | 3109C2D5147DE8190035A276 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3109C2D4147DE8190035A276 /* main.m */; }; 12 | 3109C2DE147DE8860035A276 /* libtiming.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD34147CA92A00C6B32F /* libtiming.a */; }; 13 | 31B1BD38147CA92A00C6B32F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD37147CA92A00C6B32F /* Foundation.framework */; }; 14 | 31B1BD3E147CA92A00C6B32F /* libtiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD3D147CA92A00C6B32F /* libtiming.m */; }; 15 | 31B1BD46147CA92A00C6B32F /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD45147CA92A00C6B32F /* SenTestingKit.framework */; }; 16 | 31B1BD49147CA92A00C6B32F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD37147CA92A00C6B32F /* Foundation.framework */; }; 17 | 31B1BD4C147CA92A00C6B32F /* libtiming.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B1BD34147CA92A00C6B32F /* libtiming.a */; }; 18 | 31B1BD52147CA92A00C6B32F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 31B1BD50147CA92A00C6B32F /* InfoPlist.strings */; }; 19 | 31B1BD5F147CAAF200C6B32F /* Warnings.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 31B1BD5E147CAAF200C6B32F /* Warnings.xcconfig */; }; 20 | 31B1BD63147CB1D800C6B32F /* PRHTimingBlockRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 31B1BD61147CB1D800C6B32F /* PRHTimingBlockRecord.h */; }; 21 | 31B1BD64147CB1D800C6B32F /* PRHTimingBlockRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD62147CB1D800C6B32F /* PRHTimingBlockRecord.m */; }; 22 | 31B1BD65147CB1D800C6B32F /* PRHTimingBlockRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD62147CB1D800C6B32F /* PRHTimingBlockRecord.m */; }; 23 | 31B1BD68147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.h in Headers */ = {isa = PBXBuildFile; fileRef = 31B1BD66147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.h */; }; 24 | 31B1BD69147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD67147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m */; }; 25 | 31B1BD6A147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD67147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m */; }; 26 | 31B1BD6D147CF39000C6B32F /* TestAbsoluteTimeConversions.h in Headers */ = {isa = PBXBuildFile; fileRef = 31B1BD6B147CF39000C6B32F /* TestAbsoluteTimeConversions.h */; }; 27 | 31B1BD6F147CF39000C6B32F /* TestAbsoluteTimeConversions.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B1BD6C147CF39000C6B32F /* TestAbsoluteTimeConversions.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 3109C2DF147DEAA10035A276 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 31B1BD2B147CA92A00C6B32F /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 31B1BD33147CA92A00C6B32F; 36 | remoteInfo = libtiming; 37 | }; 38 | 31B1BD4A147CA92A00C6B32F /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = 31B1BD2B147CA92A00C6B32F /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = 31B1BD33147CA92A00C6B32F; 43 | remoteInfo = libtiming; 44 | }; 45 | /* End PBXContainerItemProxy section */ 46 | 47 | /* Begin PBXCopyFilesBuildPhase section */ 48 | 3109C2CE147DE8190035A276 /* CopyFiles */ = { 49 | isa = PBXCopyFilesBuildPhase; 50 | buildActionMask = 2147483647; 51 | dstPath = /usr/share/man/man1/; 52 | dstSubfolderSpec = 0; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 1; 56 | }; 57 | /* End PBXCopyFilesBuildPhase section */ 58 | 59 | /* Begin PBXFileReference section */ 60 | 3109C2D0147DE8190035A276 /* mathtiming */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mathtiming; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 3109C2D4147DE8190035A276 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 62 | 3109C2D7147DE8190035A276 /* mathtiming-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "mathtiming-Prefix.pch"; sourceTree = ""; }; 63 | 31B1BD34147CA92A00C6B32F /* libtiming.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtiming.a; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 31B1BD37147CA92A00C6B32F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 65 | 31B1BD3B147CA92A00C6B32F /* libtiming-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "libtiming-Prefix.pch"; sourceTree = ""; }; 66 | 31B1BD3C147CA92A00C6B32F /* libtiming.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libtiming.h; sourceTree = ""; }; 67 | 31B1BD3D147CA92A00C6B32F /* libtiming.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = libtiming.m; sourceTree = ""; }; 68 | 31B1BD44147CA92A00C6B32F /* libtimingTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = libtimingTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 31B1BD45147CA92A00C6B32F /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 70 | 31B1BD4F147CA92A00C6B32F /* libtimingTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "libtimingTests-Info.plist"; sourceTree = ""; }; 71 | 31B1BD51147CA92A00C6B32F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 72 | 31B1BD5E147CAAF200C6B32F /* Warnings.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 73 | 31B1BD61147CB1D800C6B32F /* PRHTimingBlockRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PRHTimingBlockRecord.h; sourceTree = ""; }; 74 | 31B1BD62147CB1D800C6B32F /* PRHTimingBlockRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PRHTimingBlockRecord.m; sourceTree = ""; }; 75 | 31B1BD66147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PRHAbsoluteTimeToNanoseconds.h; sourceTree = ""; }; 76 | 31B1BD67147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PRHAbsoluteTimeToNanoseconds.m; sourceTree = ""; }; 77 | 31B1BD6B147CF39000C6B32F /* TestAbsoluteTimeConversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestAbsoluteTimeConversions.h; sourceTree = ""; }; 78 | 31B1BD6C147CF39000C6B32F /* TestAbsoluteTimeConversions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestAbsoluteTimeConversions.m; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 3109C2CD147DE8190035A276 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | 3109C2D2147DE8190035A276 /* Foundation.framework in Frameworks */, 87 | 3109C2DE147DE8860035A276 /* libtiming.a in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | 31B1BD31147CA92A00C6B32F /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | 31B1BD38147CA92A00C6B32F /* Foundation.framework in Frameworks */, 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | 31B1BD40147CA92A00C6B32F /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | 31B1BD46147CA92A00C6B32F /* SenTestingKit.framework in Frameworks */, 104 | 31B1BD49147CA92A00C6B32F /* Foundation.framework in Frameworks */, 105 | 31B1BD4C147CA92A00C6B32F /* libtiming.a in Frameworks */, 106 | ); 107 | runOnlyForDeploymentPostprocessing = 0; 108 | }; 109 | /* End PBXFrameworksBuildPhase section */ 110 | 111 | /* Begin PBXGroup section */ 112 | 3109C2D3147DE8190035A276 /* mathtiming */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 3109C2D4147DE8190035A276 /* main.m */, 116 | 3109C2D6147DE8190035A276 /* Supporting Files */, 117 | ); 118 | path = mathtiming; 119 | sourceTree = ""; 120 | }; 121 | 3109C2D6147DE8190035A276 /* Supporting Files */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 3109C2D7147DE8190035A276 /* mathtiming-Prefix.pch */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | 31B1BD29147CA92A00C6B32F = { 130 | isa = PBXGroup; 131 | children = ( 132 | 31B1BD39147CA92A00C6B32F /* libtiming */, 133 | 31B1BD4D147CA92A00C6B32F /* libtimingTests */, 134 | 3109C2D3147DE8190035A276 /* mathtiming */, 135 | 31B1BD36147CA92A00C6B32F /* Frameworks */, 136 | 31B1BD35147CA92A00C6B32F /* Products */, 137 | ); 138 | sourceTree = ""; 139 | }; 140 | 31B1BD35147CA92A00C6B32F /* Products */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 31B1BD34147CA92A00C6B32F /* libtiming.a */, 144 | 31B1BD44147CA92A00C6B32F /* libtimingTests.octest */, 145 | 3109C2D0147DE8190035A276 /* mathtiming */, 146 | ); 147 | name = Products; 148 | sourceTree = ""; 149 | }; 150 | 31B1BD36147CA92A00C6B32F /* Frameworks */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 31B1BD37147CA92A00C6B32F /* Foundation.framework */, 154 | 31B1BD45147CA92A00C6B32F /* SenTestingKit.framework */, 155 | ); 156 | name = Frameworks; 157 | sourceTree = ""; 158 | }; 159 | 31B1BD39147CA92A00C6B32F /* libtiming */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 31B1BD60147CB1B800C6B32F /* Public Headers */, 163 | 31B1BD3D147CA92A00C6B32F /* libtiming.m */, 164 | 31B1BD61147CB1D800C6B32F /* PRHTimingBlockRecord.h */, 165 | 31B1BD62147CB1D800C6B32F /* PRHTimingBlockRecord.m */, 166 | 31B1BD66147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.h */, 167 | 31B1BD67147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m */, 168 | 31B1BD3A147CA92A00C6B32F /* Supporting Files */, 169 | ); 170 | path = libtiming; 171 | sourceTree = ""; 172 | }; 173 | 31B1BD3A147CA92A00C6B32F /* Supporting Files */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 31B1BD5E147CAAF200C6B32F /* Warnings.xcconfig */, 177 | 31B1BD3B147CA92A00C6B32F /* libtiming-Prefix.pch */, 178 | ); 179 | name = "Supporting Files"; 180 | sourceTree = ""; 181 | }; 182 | 31B1BD4D147CA92A00C6B32F /* libtimingTests */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 31B1BD6B147CF39000C6B32F /* TestAbsoluteTimeConversions.h */, 186 | 31B1BD6C147CF39000C6B32F /* TestAbsoluteTimeConversions.m */, 187 | 31B1BD4E147CA92A00C6B32F /* Supporting Files */, 188 | ); 189 | path = libtimingTests; 190 | sourceTree = ""; 191 | }; 192 | 31B1BD4E147CA92A00C6B32F /* Supporting Files */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | 31B1BD4F147CA92A00C6B32F /* libtimingTests-Info.plist */, 196 | 31B1BD50147CA92A00C6B32F /* InfoPlist.strings */, 197 | ); 198 | name = "Supporting Files"; 199 | sourceTree = ""; 200 | }; 201 | 31B1BD60147CB1B800C6B32F /* Public Headers */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 31B1BD3C147CA92A00C6B32F /* libtiming.h */, 205 | ); 206 | name = "Public Headers"; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXGroup section */ 210 | 211 | /* Begin PBXHeadersBuildPhase section */ 212 | 31B1BD32147CA92A00C6B32F /* Headers */ = { 213 | isa = PBXHeadersBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 31B1BD63147CB1D800C6B32F /* PRHTimingBlockRecord.h in Headers */, 217 | 31B1BD68147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.h in Headers */, 218 | 31B1BD6D147CF39000C6B32F /* TestAbsoluteTimeConversions.h in Headers */, 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | }; 222 | /* End PBXHeadersBuildPhase section */ 223 | 224 | /* Begin PBXNativeTarget section */ 225 | 3109C2CF147DE8190035A276 /* mathtiming */ = { 226 | isa = PBXNativeTarget; 227 | buildConfigurationList = 3109C2DC147DE8190035A276 /* Build configuration list for PBXNativeTarget "mathtiming" */; 228 | buildPhases = ( 229 | 3109C2CC147DE8190035A276 /* Sources */, 230 | 3109C2CD147DE8190035A276 /* Frameworks */, 231 | 3109C2CE147DE8190035A276 /* CopyFiles */, 232 | ); 233 | buildRules = ( 234 | ); 235 | dependencies = ( 236 | 3109C2E0147DEAA10035A276 /* PBXTargetDependency */, 237 | ); 238 | name = mathtiming; 239 | productName = mathtiming; 240 | productReference = 3109C2D0147DE8190035A276 /* mathtiming */; 241 | productType = "com.apple.product-type.tool"; 242 | }; 243 | 31B1BD33147CA92A00C6B32F /* libtiming */ = { 244 | isa = PBXNativeTarget; 245 | buildConfigurationList = 31B1BD58147CA92A00C6B32F /* Build configuration list for PBXNativeTarget "libtiming" */; 246 | buildPhases = ( 247 | 31B1BD30147CA92A00C6B32F /* Sources */, 248 | 31B1BD31147CA92A00C6B32F /* Frameworks */, 249 | 31B1BD32147CA92A00C6B32F /* Headers */, 250 | ); 251 | buildRules = ( 252 | ); 253 | dependencies = ( 254 | ); 255 | name = libtiming; 256 | productName = libtiming; 257 | productReference = 31B1BD34147CA92A00C6B32F /* libtiming.a */; 258 | productType = "com.apple.product-type.library.static"; 259 | }; 260 | 31B1BD43147CA92A00C6B32F /* libtimingTests */ = { 261 | isa = PBXNativeTarget; 262 | buildConfigurationList = 31B1BD5B147CA92A00C6B32F /* Build configuration list for PBXNativeTarget "libtimingTests" */; 263 | buildPhases = ( 264 | 31B1BD3F147CA92A00C6B32F /* Sources */, 265 | 31B1BD40147CA92A00C6B32F /* Frameworks */, 266 | 31B1BD41147CA92A00C6B32F /* Resources */, 267 | 31B1BD42147CA92A00C6B32F /* ShellScript */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | 31B1BD4B147CA92A00C6B32F /* PBXTargetDependency */, 273 | ); 274 | name = libtimingTests; 275 | productName = libtimingTests; 276 | productReference = 31B1BD44147CA92A00C6B32F /* libtimingTests.octest */; 277 | productType = "com.apple.product-type.bundle"; 278 | }; 279 | /* End PBXNativeTarget section */ 280 | 281 | /* Begin PBXProject section */ 282 | 31B1BD2B147CA92A00C6B32F /* Project object */ = { 283 | isa = PBXProject; 284 | attributes = { 285 | LastUpgradeCheck = 0420; 286 | }; 287 | buildConfigurationList = 31B1BD2E147CA92A00C6B32F /* Build configuration list for PBXProject "libtiming" */; 288 | compatibilityVersion = "Xcode 3.2"; 289 | developmentRegion = English; 290 | hasScannedForEncodings = 0; 291 | knownRegions = ( 292 | en, 293 | ); 294 | mainGroup = 31B1BD29147CA92A00C6B32F; 295 | productRefGroup = 31B1BD35147CA92A00C6B32F /* Products */; 296 | projectDirPath = ""; 297 | projectRoot = ""; 298 | targets = ( 299 | 31B1BD33147CA92A00C6B32F /* libtiming */, 300 | 31B1BD43147CA92A00C6B32F /* libtimingTests */, 301 | 3109C2CF147DE8190035A276 /* mathtiming */, 302 | ); 303 | }; 304 | /* End PBXProject section */ 305 | 306 | /* Begin PBXResourcesBuildPhase section */ 307 | 31B1BD41147CA92A00C6B32F /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | 31B1BD52147CA92A00C6B32F /* InfoPlist.strings in Resources */, 312 | 31B1BD5F147CAAF200C6B32F /* Warnings.xcconfig in Resources */, 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | /* End PBXResourcesBuildPhase section */ 317 | 318 | /* Begin PBXShellScriptBuildPhase section */ 319 | 31B1BD42147CA92A00C6B32F /* ShellScript */ = { 320 | isa = PBXShellScriptBuildPhase; 321 | buildActionMask = 2147483647; 322 | files = ( 323 | ); 324 | inputPaths = ( 325 | ); 326 | outputPaths = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 331 | }; 332 | /* End PBXShellScriptBuildPhase section */ 333 | 334 | /* Begin PBXSourcesBuildPhase section */ 335 | 3109C2CC147DE8190035A276 /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 3109C2D5147DE8190035A276 /* main.m in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | 31B1BD30147CA92A00C6B32F /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 31B1BD3E147CA92A00C6B32F /* libtiming.m in Sources */, 348 | 31B1BD64147CB1D800C6B32F /* PRHTimingBlockRecord.m in Sources */, 349 | 31B1BD69147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m in Sources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | 31B1BD3F147CA92A00C6B32F /* Sources */ = { 354 | isa = PBXSourcesBuildPhase; 355 | buildActionMask = 2147483647; 356 | files = ( 357 | 31B1BD65147CB1D800C6B32F /* PRHTimingBlockRecord.m in Sources */, 358 | 31B1BD6A147CF1AF00C6B32F /* PRHAbsoluteTimeToNanoseconds.m in Sources */, 359 | 31B1BD6F147CF39000C6B32F /* TestAbsoluteTimeConversions.m in Sources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | /* End PBXSourcesBuildPhase section */ 364 | 365 | /* Begin PBXTargetDependency section */ 366 | 3109C2E0147DEAA10035A276 /* PBXTargetDependency */ = { 367 | isa = PBXTargetDependency; 368 | target = 31B1BD33147CA92A00C6B32F /* libtiming */; 369 | targetProxy = 3109C2DF147DEAA10035A276 /* PBXContainerItemProxy */; 370 | }; 371 | 31B1BD4B147CA92A00C6B32F /* PBXTargetDependency */ = { 372 | isa = PBXTargetDependency; 373 | target = 31B1BD33147CA92A00C6B32F /* libtiming */; 374 | targetProxy = 31B1BD4A147CA92A00C6B32F /* PBXContainerItemProxy */; 375 | }; 376 | /* End PBXTargetDependency section */ 377 | 378 | /* Begin PBXVariantGroup section */ 379 | 31B1BD50147CA92A00C6B32F /* InfoPlist.strings */ = { 380 | isa = PBXVariantGroup; 381 | children = ( 382 | 31B1BD51147CA92A00C6B32F /* en */, 383 | ); 384 | name = InfoPlist.strings; 385 | sourceTree = ""; 386 | }; 387 | /* End PBXVariantGroup section */ 388 | 389 | /* Begin XCBuildConfiguration section */ 390 | 3109C2DA147DE8190035A276 /* Debug */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 394 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 395 | GCC_PREFIX_HEADER = "mathtiming/mathtiming-Prefix.pch"; 396 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 397 | MACOSX_DEPLOYMENT_TARGET = 10.7; 398 | ONLY_ACTIVE_ARCH = YES; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | SDKROOT = macosx; 401 | }; 402 | name = Debug; 403 | }; 404 | 3109C2DB147DE8190035A276 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 408 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 409 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 410 | GCC_PREFIX_HEADER = "mathtiming/mathtiming-Prefix.pch"; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | MACOSX_DEPLOYMENT_TARGET = 10.7; 413 | PRODUCT_NAME = "$(TARGET_NAME)"; 414 | SDKROOT = macosx; 415 | }; 416 | name = Release; 417 | }; 418 | 31B1BD56147CA92A00C6B32F /* Debug */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 423 | CLANG_ENABLE_OBJC_ARC = YES; 424 | COPY_PHASE_STRIP = NO; 425 | GCC_C_LANGUAGE_STANDARD = gnu99; 426 | GCC_DYNAMIC_NO_PIC = NO; 427 | GCC_OPTIMIZATION_LEVEL = 0; 428 | GCC_PREPROCESSOR_DEFINITIONS = ( 429 | "DEBUG=1", 430 | "$(inherited)", 431 | ); 432 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 433 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 434 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 435 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 436 | GCC_WARN_UNUSED_VARIABLE = YES; 437 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 438 | SDKROOT = macosx10.7; 439 | }; 440 | name = Debug; 441 | }; 442 | 31B1BD57147CA92A00C6B32F /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 447 | CLANG_ENABLE_OBJC_ARC = YES; 448 | COPY_PHASE_STRIP = YES; 449 | GCC_C_LANGUAGE_STANDARD = gnu99; 450 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 451 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 452 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 453 | GCC_WARN_UNUSED_VARIABLE = YES; 454 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 455 | SDKROOT = macosx10.7; 456 | VALIDATE_PRODUCT = YES; 457 | }; 458 | name = Release; 459 | }; 460 | 31B1BD59147CA92A00C6B32F /* Debug */ = { 461 | isa = XCBuildConfiguration; 462 | baseConfigurationReference = 31B1BD5E147CAAF200C6B32F /* Warnings.xcconfig */; 463 | buildSettings = { 464 | DSTROOT = /tmp/libtiming.dst; 465 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 466 | GCC_PREFIX_HEADER = "libtiming/libtiming-Prefix.pch"; 467 | OTHER_LDFLAGS = "-ObjC"; 468 | PRODUCT_NAME = timing; 469 | SKIP_INSTALL = YES; 470 | }; 471 | name = Debug; 472 | }; 473 | 31B1BD5A147CA92A00C6B32F /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | baseConfigurationReference = 31B1BD5E147CAAF200C6B32F /* Warnings.xcconfig */; 476 | buildSettings = { 477 | DSTROOT = /tmp/libtiming.dst; 478 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 479 | GCC_PREFIX_HEADER = "libtiming/libtiming-Prefix.pch"; 480 | OTHER_LDFLAGS = "-ObjC"; 481 | PRODUCT_NAME = timing; 482 | SKIP_INSTALL = YES; 483 | }; 484 | name = Release; 485 | }; 486 | 31B1BD5C147CA92A00C6B32F /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 490 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 491 | GCC_PREFIX_HEADER = "libtiming/libtiming-Prefix.pch"; 492 | INFOPLIST_FILE = "libtimingTests/libtimingTests-Info.plist"; 493 | PRODUCT_NAME = "$(TARGET_NAME)"; 494 | WRAPPER_EXTENSION = octest; 495 | }; 496 | name = Debug; 497 | }; 498 | 31B1BD5D147CA92A00C6B32F /* Release */ = { 499 | isa = XCBuildConfiguration; 500 | buildSettings = { 501 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 502 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 503 | GCC_PREFIX_HEADER = "libtiming/libtiming-Prefix.pch"; 504 | INFOPLIST_FILE = "libtimingTests/libtimingTests-Info.plist"; 505 | PRODUCT_NAME = "$(TARGET_NAME)"; 506 | WRAPPER_EXTENSION = octest; 507 | }; 508 | name = Release; 509 | }; 510 | /* End XCBuildConfiguration section */ 511 | 512 | /* Begin XCConfigurationList section */ 513 | 3109C2DC147DE8190035A276 /* Build configuration list for PBXNativeTarget "mathtiming" */ = { 514 | isa = XCConfigurationList; 515 | buildConfigurations = ( 516 | 3109C2DA147DE8190035A276 /* Debug */, 517 | 3109C2DB147DE8190035A276 /* Release */, 518 | ); 519 | defaultConfigurationIsVisible = 0; 520 | }; 521 | 31B1BD2E147CA92A00C6B32F /* Build configuration list for PBXProject "libtiming" */ = { 522 | isa = XCConfigurationList; 523 | buildConfigurations = ( 524 | 31B1BD56147CA92A00C6B32F /* Debug */, 525 | 31B1BD57147CA92A00C6B32F /* Release */, 526 | ); 527 | defaultConfigurationIsVisible = 0; 528 | defaultConfigurationName = Release; 529 | }; 530 | 31B1BD58147CA92A00C6B32F /* Build configuration list for PBXNativeTarget "libtiming" */ = { 531 | isa = XCConfigurationList; 532 | buildConfigurations = ( 533 | 31B1BD59147CA92A00C6B32F /* Debug */, 534 | 31B1BD5A147CA92A00C6B32F /* Release */, 535 | ); 536 | defaultConfigurationIsVisible = 0; 537 | defaultConfigurationName = Release; 538 | }; 539 | 31B1BD5B147CA92A00C6B32F /* Build configuration list for PBXNativeTarget "libtimingTests" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 31B1BD5C147CA92A00C6B32F /* Debug */, 543 | 31B1BD5D147CA92A00C6B32F /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | /* End XCConfigurationList section */ 549 | }; 550 | rootObject = 31B1BD2B147CA92A00C6B32F /* Project object */; 551 | } 552 | --------------------------------------------------------------------------------