iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
時間を計測する関数には、色々な種類がある。どのような精度の値が取得できるかも重要だが、その関数を呼び出すコストも重要になる。
以前、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の呼び出しコストが最も軽いみたい。