blob: 4d924b435a99d37d5d8d053bf71aba8e53fc9f9e [file] [log] [blame]
mostang.com!davidme1da7182004-01-21 06:36:35 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2003-2004 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
mostang.com!davidm96c62502004-03-27 09:25:58 +000024#include <memory.h>
mostang.com!davidm12876ef2003-09-24 05:02:14 +000025#include <stdio.h>
26#include <stdlib.h>
27
mostang.com!davidmc7fdc722004-03-20 09:54:28 +000028#include <time.h>
mostang.com!davidm12876ef2003-09-24 05:02:14 +000029
30#include <libunwind.h>
31
32#define panic(args...) \
33 do { fprintf (stderr, args); exit (-1); } while (0)
34
mostang.com!davidm96c62502004-03-27 09:25:58 +000035long dummy;
36
mostang.com!davidmc7fdc722004-03-20 09:54:28 +000037static long iterations = 10000;
hp.com!davidm5e446b22003-11-27 06:52:54 +000038static int maxlevel = 100;
39
mostang.com!davidm96c62502004-03-27 09:25:58 +000040#define MB (1024*1024)
41
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +000042static char big[512*MB];
mostang.com!davidm96c62502004-03-27 09:25:58 +000043
mostang.com!davidm12876ef2003-09-24 05:02:14 +000044static inline double
45gettime (void)
46{
mostang.com!davidmc7fdc722004-03-20 09:54:28 +000047 struct timespec ts;
mostang.com!davidm12876ef2003-09-24 05:02:14 +000048
mostang.com!davidmc7fdc722004-03-20 09:54:28 +000049 clock_gettime(CLOCK_REALTIME, &ts);
50 return ts.tv_sec + 1e-9*ts.tv_nsec;
mostang.com!davidm12876ef2003-09-24 05:02:14 +000051}
52
53static int
mostang.com!davidm96c62502004-03-27 09:25:58 +000054measure_unwind (int maxlevel, double *step)
mostang.com!davidm12876ef2003-09-24 05:02:14 +000055{
mostang.com!davidm96c62502004-03-27 09:25:58 +000056 double stop, start;
mostang.com!davidm12876ef2003-09-24 05:02:14 +000057 unw_cursor_t cursor;
58 unw_context_t uc;
59 int ret, level = 0;
60
mostang.com!davidm12876ef2003-09-24 05:02:14 +000061 unw_getcontext (&uc);
62 if (unw_init_local (&cursor, &uc) < 0)
63 panic ("unw_init_local() failed\n");
64
mostang.com!davidm96c62502004-03-27 09:25:58 +000065 start = gettime ();
mostang.com!davidm12876ef2003-09-24 05:02:14 +000066
67 do
68 {
69 ret = unw_step (&cursor);
70 if (ret < 0)
71 panic ("unw_step() failed\n");
72 ++level;
73 }
74 while (ret > 0);
75
76 stop = gettime ();
77
78 if (level <= maxlevel)
79 panic ("Unwound only %d levels, expected at least %d levels",
80 level, maxlevel);
81
mostang.com!davidm96c62502004-03-27 09:25:58 +000082 *step = (stop - start) / (double) level;
hp.com!davidm29f2f892003-09-25 05:29:14 +000083 return 0;
mostang.com!davidm12876ef2003-09-24 05:02:14 +000084}
85
86static int
mostang.com!davidm96c62502004-03-27 09:25:58 +000087f1 (int level, int maxlevel, double *step)
mostang.com!davidm12876ef2003-09-24 05:02:14 +000088{
89 if (level == maxlevel)
mostang.com!davidm96c62502004-03-27 09:25:58 +000090 return measure_unwind (maxlevel, step);
mostang.com!davidm12876ef2003-09-24 05:02:14 +000091 else
92 /* defeat last-call/sibcall optimization */
mostang.com!davidm96c62502004-03-27 09:25:58 +000093 return f1 (level + 1, maxlevel, step) + level;
hp.com!davidm5e446b22003-11-27 06:52:54 +000094}
95
96static void
97doit (const char *label)
98{
mostang.com!davidm96c62502004-03-27 09:25:58 +000099 double step, min_step, first_step, sum_step;
hp.com!davidm5e446b22003-11-27 06:52:54 +0000100 int i;
101
mostang.com!davidm96c62502004-03-27 09:25:58 +0000102 sum_step = first_step = 0.0;
103 min_step = 1e99;
mostang.com!davidmc7fdc722004-03-20 09:54:28 +0000104 for (i = 0; i < iterations; ++i)
hp.com!davidm5e446b22003-11-27 06:52:54 +0000105 {
mostang.com!davidm96c62502004-03-27 09:25:58 +0000106 f1 (0, maxlevel, &step);
hp.com!davidm5e446b22003-11-27 06:52:54 +0000107
hp.com!davidm5e446b22003-11-27 06:52:54 +0000108 sum_step += step;
109
hp.com!davidm5e446b22003-11-27 06:52:54 +0000110 if (step < min_step)
111 min_step = step;
112
113 if (i == 0)
mostang.com!davidm96c62502004-03-27 09:25:58 +0000114 first_step = step;
hp.com!davidm5e446b22003-11-27 06:52:54 +0000115 }
mostang.com!davidm96c62502004-03-27 09:25:58 +0000116 printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label,
mostang.com!davidmc7fdc722004-03-20 09:54:28 +0000117 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations);
mostang.com!davidm12876ef2003-09-24 05:02:14 +0000118}
119
mostang.com!davidm96c62502004-03-27 09:25:58 +0000120static long
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000121sum (void *buf, size_t size)
mostang.com!davidm96c62502004-03-27 09:25:58 +0000122{
123 long s = 0;
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000124 char *cp = buf;
mostang.com!davidm96c62502004-03-27 09:25:58 +0000125 size_t i;
126
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000127 for (i = 0; i < size; i += 64)
128 s += *cp++;
mostang.com!davidm96c62502004-03-27 09:25:58 +0000129 return s;
130}
131
132static void
133measure_init (void)
134{
135# define N 1000
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000136# define M 10
137 double stop, start, get_cold, get_warm, init_cold, init_warm, delta;
mostang.com!davidm96c62502004-03-27 09:25:58 +0000138 unw_cursor_t cursor[N];
139 unw_context_t uc[N];
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000140 int i, j;
mostang.com!davidm96c62502004-03-27 09:25:58 +0000141
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000142 /* Run each test M times and take the minimum to filter out noise
143 such dynamic linker resolving overhead, context-switches,
144 page-in, cache, and TLB effects. */
mostang.com!davidm96c62502004-03-27 09:25:58 +0000145
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000146 get_cold = 1e99;
147 for (j = 0; j < M; ++j)
148 {
149 dummy += sum (big, sizeof (big)); /* flush the cache */
mostang.com!davidm96c62502004-03-27 09:25:58 +0000150
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000151 start = gettime ();
152 for (i = 0; i < N; ++i)
153 unw_getcontext (&uc[i]);
154 stop = gettime ();
155 delta = (stop - start) / N;
156 if (delta < get_cold)
157 get_cold = delta;
158 }
159 //exit (0);
160 init_cold = 1e99;
161 for (j = 0; j < M; ++j)
162 {
163 dummy += sum (big, sizeof (big)); /* flush cache */
164 start = gettime ();
165 for (i = 0; i < N; ++i)
166 unw_init_local (&cursor[i], &uc[i]);
167 stop = gettime ();
168 delta = (stop - start) / N;
169 if (delta < init_cold)
170 init_cold = delta;
171 }
mostang.com!davidm96c62502004-03-27 09:25:58 +0000172
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000173 get_warm = 1e99;
174 for (j = 0; j < M; ++j)
175 {
176 start = gettime ();
177 for (i = 0; i < N; ++i)
178 unw_getcontext (&uc[0]);
179 stop = gettime ();
180 delta = (stop - start) / N;
181 if (delta < get_warm)
182 get_warm = delta;
183 }
mostang.com!davidm96c62502004-03-27 09:25:58 +0000184
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000185 init_warm = 1e99;
186 for (j = 0; j < M; ++j)
187 {
188 start = gettime ();
189 for (i = 0; i < N; ++i)
190 unw_init_local (&cursor[0], &uc[0]);
191 stop = gettime ();
192 delta = (stop - start) / N;
193 if (delta < init_warm)
194 init_warm = delta;
195 }
mostang.com!davidm96c62502004-03-27 09:25:58 +0000196
197 printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
mostang.com!davidmfc7b49b2004-03-28 00:24:33 +0000198 1e9 * get_cold, 1e9 * get_warm);
mostang.com!davidm96c62502004-03-27 09:25:58 +0000199 printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n",
200 1e9 * init_cold, 1e9 * init_warm);
201}
202
mostang.com!davidm12876ef2003-09-24 05:02:14 +0000203int
204main (int argc, char **argv)
205{
mostang.com!davidm12876ef2003-09-24 05:02:14 +0000206 if (argc > 1)
mostang.com!davidmc7fdc722004-03-20 09:54:28 +0000207 {
208 maxlevel = atol (argv[1]);
209 if (argc > 2)
210 iterations = atol (argv[2]);
211 }
mostang.com!davidm12876ef2003-09-24 05:02:14 +0000212
mostang.com!davidm96c62502004-03-27 09:25:58 +0000213 measure_init ();
214
mostang.com!davidm7a346fb2003-11-20 01:10:03 +0000215 unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE);
mostang.com!davidm96c62502004-03-27 09:25:58 +0000216 doit ("no cache ");
mostang.com!davidm7a346fb2003-11-20 01:10:03 +0000217
mostang.com!davidm7a346fb2003-11-20 01:10:03 +0000218 unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL);
mostang.com!davidm96c62502004-03-27 09:25:58 +0000219 doit ("global cache ");
mostang.com!davidm7a346fb2003-11-20 01:10:03 +0000220
mostang.com!davidm7a346fb2003-11-20 01:10:03 +0000221 unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD);
mostang.com!davidm96c62502004-03-27 09:25:58 +0000222 doit ("per-thread cache");
hp.com!davidm5e446b22003-11-27 06:52:54 +0000223
mostang.com!davidm12876ef2003-09-24 05:02:14 +0000224 return 0;
225}