トップ «前の日記(2012-01-20) 最新 次の日記(2012-01-22)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|

2012-01-21 [Mac]高分解能実時間

時間を計測する関数には、色々な種類がある。どのような精度の値が取得できるかも重要だが、その関数を呼び出すコストも重要になる。

以前、Cocoa勉強会の発表の為に調べた、各種の時間取得関数は以下のとおり。現在では、使用できない物もあるが、そのまま、掲載している。

種類 モジュール 関数
ANSI C 標準ライブラリ clock
time
Mach Clock Interface clock_get_time
Mach Absolute Time Units mach_absolute_time
カーネル開発 カーネル・ライブラリ clock_get_uptime
clock_get_system_value
clock_get_calendar_value
clock_get_calendar_offset
BSD POSIX gettimeofday
Core Foundation CarbonLib CFAbsoluteTimeGetCurrent
Carbon デバイス・ドライバー UpTime
OS Utilities ReadDateTime
Date, Time, and Measurement Utilities GetDateTime
Cocoa NSDate +timeIntervalSince1970:
+timeIntervalSinceReferenceDate:

Lionで呼び出す事が可能な関数について、複数回のループ内で呼び出して、ループ全体にかかる時間を測定したのが、以下のコード。

#import <Foundation/Foundation.h>
#import <stdio.h>
#import <sys/time.h>
#import <mach/mach.h>
/* #import <CoreServices/CoreServices.h> */
 
#define TIMERSUB(a, b, result)                              \
    do {                                                    \
        (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;       \
        (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;    \
        if ((result)->tv_usec < 0) {                        \
            --(result)->tv_sec;                             \
            (result)->tv_usec += 1000000;                   \
        }                                                   \
    } while (0)
 
int main (int argc, const char * argv[])
{
	int				i, j;
	clock_serv_t		clock_serv;
	mach_timespec_t	cur_time;
	struct timeval		tv_start, tv_end, tv_diff;
    /* AbsoluteTime		at_start; */
	/* float				deltaTime; */
	/* uint64_t			result; */
	/* unsigned long		secs; */
 
    @autoreleasepool {
        
        /* ANSI C: clock_t clock(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                clock();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("ANSI C: clock: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* ANSI C: time_t time(time_t *pSec) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                time(NULL);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("ANSI C: time: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Mach: kern_return_t clock_get_time(clock_serv_t clock_serv, mach_timespec_t *cur_time) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_serv);
                clock_get_time(clock_serv, &cur_time);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: clock_get_time: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Mach: uint64_t mach_absolute_time(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                mach_absolute_time();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: mach_absolute_time: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
#if 0
        /* Kernel: void clock_get_uptime(uint64_t *result) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                clock_get_uptime(&result);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: clock_get_uptime: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Kernel: mach_timespec_t clock_get_system_value(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                clock_get_system_value();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: clock_get_system_value: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Kernel: mach_timespec_t clock_get_calendar_value(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                clock_get_calendar_value();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: clock_get_calendar_value: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Kernel: mach_timespec_t clock_get_calendar_offset(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                clock_get_calendar_offset();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Mach: clock_get_calendar_offset: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
#endif /* 0 */
        
        /* POSIX: int gettimeofday(struct timeval *tv, struct timezone *tz) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                gettimeofday(&tv_end, NULL);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("POSIX: gettimeofday: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Core Foundation: CFAbsoluteTimeGetCurrent */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                CFAbsoluteTimeGetCurrent();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Core Foundation: CFAbsoluteTimeGetCurrent: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
#if 0
        /* Carbon: UpTime */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                UpTime();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Carbon: UpTime: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
#endif /* 0 */
 
#if 0
        /* Carbon: ReadDateTime */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                ReadDateTime(&secs);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Carbon: ReadDateTime: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
#endif /* 0 */
 
#if 0
        /* Carbon: GetDateTime */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                GetDateTime(&secs);
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Carbon: GetDateTime: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
#endif /* 0 */
 
        /* Cocoa: NSDate::timeIntervalSince1970 */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                [[NSDate date] timeIntervalSince1970];
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Cocoa: NSDate::timeIntervalSince1970: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
        /* Cocoa: NSDate::timeIntervalSinceReferenceDate */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                [[NSDate date] timeIntervalSinceReferenceDate];
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Cocoa: NSDate::timeIntervalSinceReferenceDate: %ld.%06d[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
        
#if 0
        /* Unsupported: hrtime_t gethrtime(void) */
        gettimeofday(&tv_start, NULL);
        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 100; j++) {
                gethrtime();
            }
        }
        gettimeofday(&tv_end, NULL);
        TIMERSUB(&tv_end, &tv_start, &tv_diff);
        printf("Unsupported: gethrtime: %ld.%06ld[sec]\n", tv_diff.tv_sec, tv_diff.tv_usec);
#endif /* 0 */
        
    }
    return 0;
}

mach_absolute_timeの呼び出しコストが最も軽いみたい。

_ 関連情報

Technical Q&A QA1398 Mach Absolute Time Unit
mach_absolute_timeの説明です。
Technical Q&A QA1643 Audio Host Time On iPhone OS
iOSで、AudioGetCurrentHostTimeとAudioGetHostClockFrequencyに代わってmach_absolute_timeを利用する説明です。

トップ «前の日記(2012-01-20) 最新 次の日記(2012-01-22)» 編集