Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / src / benchmark.c
1 /*
2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  * 
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  * 
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  * 
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * 
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20
21 #include "internal.h"
22
23
24 struct __dispatch_benchmark_data_s {
25 #if HAVE_MACH_ABSOLUTE_TIME
26         mach_timebase_info_data_t tbi;
27 #endif
28         uint64_t loop_cost;
29         void (*func)(void *);
30         void *ctxt;
31         size_t count;
32 };
33
34 static void
35 _dispatch_benchmark_init(void *context)
36 {
37         struct __dispatch_benchmark_data_s *bdata = context;
38         // try and simulate performance of real benchmark as much as possible
39         // keep 'f', 'c' and 'cnt' in registers
40         register void (*f)(void *) = bdata->func;
41         register void *c = bdata->ctxt;
42         register size_t cnt = bdata->count;
43         size_t i = 0;
44         uint64_t start, delta;
45 #ifdef __LP64__
46         __uint128_t lcost;
47 #else
48         long double lcost;
49 #endif
50 #if HAVE_MACH_ABSOLUTE_TIME
51         kern_return_t kr;
52
53         kr = mach_timebase_info(&bdata->tbi);
54         dispatch_assert_zero(kr);
55 #endif
56
57         start = _dispatch_absolute_time();
58         do {
59                 i++;
60                 f(c);
61         } while (i < cnt);
62         delta = _dispatch_absolute_time() - start;
63
64         lcost = delta;
65 #if HAVE_MACH_ABSOLUTE_TIME
66         lcost *= bdata->tbi.numer;
67         lcost /= bdata->tbi.denom;
68 #endif
69         lcost /= cnt;
70
71         bdata->loop_cost = lcost;
72 }
73
74 #ifdef __BLOCKS__
75 uint64_t
76 dispatch_benchmark(size_t count, void (^block)(void))
77 {
78         struct Block_basic *bb = (void *)block;
79         return dispatch_benchmark_f(count, block, (void *)bb->Block_invoke);
80 }
81 #endif
82
83 uint64_t
84 dispatch_benchmark_f(size_t count, register void *ctxt, register void (*func)(void *))
85 {
86         static struct __dispatch_benchmark_data_s bdata = {
87                 .func = (void *)dummy_function,
88                 .count = 10000000ul, // ten million
89         };
90         static dispatch_once_t pred;
91         uint64_t ns, start, delta;
92 #ifdef __LP64__
93         __uint128_t conversion, big_denom;
94 #else
95         long double conversion, big_denom;
96 #endif
97         size_t i = 0;
98
99         dispatch_once_f(&pred, &bdata, _dispatch_benchmark_init);
100
101         if (slowpath(count == 0)) {
102                 return 0;
103         }
104
105         start = _dispatch_absolute_time();
106         do {
107                 i++;
108                 func(ctxt);
109         } while (i < count);
110         delta = _dispatch_absolute_time() - start;
111
112         conversion = delta;
113 #if HAVE_MACH_ABSOLUTE_TIME
114         conversion *= bdata.tbi.numer;
115         big_denom = bdata.tbi.denom;
116 #else
117         big_denom = delta;
118 #endif
119         big_denom *= count;
120         conversion /= big_denom;
121         ns = conversion;
122
123         return ns - bdata.loop_cost;
124 }