Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers prof.c Source File

prof.c

00001 /*
00002  * Profiling framework for the events library
00003  *
00004  * Copyright (c) 2016 ARM Limited
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 #include "events/equeue.h"
00019 #include <unistd.h>
00020 #include <stdio.h>
00021 #include <setjmp.h>
00022 #include <stdint.h>
00023 #include <stdlib.h>
00024 #include <inttypes.h>
00025 #include <sys/time.h>
00026 
00027 
00028 // Performance measurement utils
00029 #define PROF_RUNS 5
00030 #define PROF_INTERVAL 100000000
00031 
00032 #define prof_volatile(t) __attribute__((unused)) volatile t
00033 
00034 typedef uint64_t prof_cycle_t;
00035 
00036 static volatile prof_cycle_t prof_start_cycle;
00037 static volatile prof_cycle_t prof_stop_cycle;
00038 static prof_cycle_t prof_accum_cycle;
00039 static prof_cycle_t prof_baseline_cycle;
00040 static prof_cycle_t prof_iterations;
00041 static const char *prof_units;
00042 
00043 #define prof_cycle() ({                                                     \
00044     uint32_t a, b;                                                          \
00045     __asm__ volatile ("rdtsc" : "=a" (a), "=d" (b));                        \
00046     ((uint64_t)b << 32) | (uint64_t)a;                                      \
00047 })
00048 
00049 #define prof_loop()                                                         \
00050     for (prof_iterations = 0;                                               \
00051          prof_accum_cycle < PROF_INTERVAL;                                  \
00052          prof_iterations++)
00053 
00054 #define prof_start() ({                                                     \
00055     prof_start_cycle = prof_cycle();                                        \
00056 })
00057 
00058 #define prof_stop() ({                                                      \
00059     prof_stop_cycle = prof_cycle();                                         \
00060     prof_accum_cycle += prof_stop_cycle - prof_start_cycle;                 \
00061 })
00062 
00063 #define prof_result(value, units) ({                                        \
00064     prof_accum_cycle = value+prof_baseline_cycle;                           \
00065     prof_iterations = 1;                                                    \
00066     prof_units = units;                                                     \
00067 })
00068 
00069 #define prof_measure(func, ...) ({                                          \
00070     printf("%s: ...", #func);                                               \
00071     fflush(stdout);                                                         \
00072                                                                             \
00073     prof_units = "cycles";                                                  \
00074     prof_cycle_t runs[PROF_RUNS];                                           \
00075     for (int i = 0; i < PROF_RUNS; i++) {                                   \
00076         prof_accum_cycle = 0;                                               \
00077         prof_iterations = 0;                                                \
00078         func(__VA_ARGS__);                                                  \
00079         runs[i] = prof_accum_cycle / prof_iterations;                       \
00080     }                                                                       \
00081                                                                             \
00082     prof_cycle_t res = runs[0];                                             \
00083     for (int i = 0; i < PROF_RUNS; i++) {                                   \
00084         if (runs[i] < res) {                                                \
00085             res = runs[i];                                                  \
00086         }                                                                   \
00087     }                                                                       \
00088     res -= prof_baseline_cycle;                                             \
00089     printf("\r%s: %"PRIu64" %s", #func, res, prof_units);                   \
00090                                                                             \
00091     if (!isatty(0)) {                                                       \
00092         prof_cycle_t prev;                                                  \
00093         while (scanf("%*[^0-9]%"PRIu64, &prev) == 0);                       \
00094         int64_t perc = 100*((int64_t)prev - (int64_t)res) / (int64_t)prev;  \
00095                                                                             \
00096         if (perc > 10) {                                                    \
00097             printf(" (\e[32m%+"PRId64"%%\e[0m)", perc);                     \
00098         } else if (perc < -10) {                                            \
00099             printf(" (\e[31m%+"PRId64"%%\e[0m)", perc);                     \
00100         } else {                                                            \
00101             printf(" (%+"PRId64"%%)", perc);                                \
00102         }                                                                   \
00103     }                                                                       \
00104                                                                             \
00105     printf("\n");                                                           \
00106     res;                                                                    \
00107 })
00108 
00109 #define prof_baseline(func, ...) ({                                         \
00110     prof_baseline_cycle = 0;                                                \
00111     prof_baseline_cycle = prof_measure(func, __VA_ARGS__);                  \
00112 })
00113 
00114 
00115 // Various test functions
00116 void no_func(void *eh)
00117 {
00118 }
00119 
00120 
00121 // Actual performance tests
00122 void baseline_prof(void)
00123 {
00124     prof_loop() {
00125         prof_start();
00126         __asm__ volatile("");
00127         prof_stop();
00128     }
00129 }
00130 
00131 void equeue_tick_prof(void)
00132 {
00133     prof_volatile(unsigned) res;
00134     prof_loop() {
00135         prof_start();
00136         res = equeue_tick();
00137         prof_stop();
00138     }
00139 }
00140 
00141 void equeue_alloc_prof(void)
00142 {
00143     struct equeue q;
00144     equeue_create(&q, 32 * EQUEUE_EVENT_SIZE);
00145 
00146     prof_loop() {
00147         prof_start();
00148         void *e = equeue_alloc(&q, 8 * sizeof(int));
00149         prof_stop();
00150 
00151         equeue_dealloc(&q, e);
00152     }
00153 
00154     equeue_destroy(&q);
00155 }
00156 
00157 void equeue_alloc_many_prof(int count)
00158 {
00159     struct equeue q;
00160     equeue_create(&q, count * EQUEUE_EVENT_SIZE);
00161 
00162     void *es[count];
00163 
00164     for (int i = 0; i < count; i++) {
00165         es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
00166     }
00167 
00168     for (int i = 0; i < count; i++) {
00169         equeue_dealloc(&q, es[i]);
00170     }
00171 
00172     prof_loop() {
00173         prof_start();
00174         void *e = equeue_alloc(&q, 8 * sizeof(int));
00175         prof_stop();
00176 
00177         equeue_dealloc(&q, e);
00178     }
00179 
00180     equeue_destroy(&q);
00181 }
00182 
00183 void equeue_post_prof(void)
00184 {
00185     struct equeue q;
00186     equeue_create(&q, EQUEUE_EVENT_SIZE);
00187 
00188     prof_loop() {
00189         void *e = equeue_alloc(&q, 0);
00190 
00191         prof_start();
00192         int id = equeue_post(&q, no_func, e);
00193         prof_stop();
00194 
00195         equeue_cancel(&q, id);
00196     }
00197 
00198     equeue_destroy(&q);
00199 }
00200 
00201 void equeue_post_many_prof(int count)
00202 {
00203     struct equeue q;
00204     equeue_create(&q, count * EQUEUE_EVENT_SIZE);
00205 
00206     for (int i = 0; i < count - 1; i++) {
00207         equeue_call(&q, no_func, 0);
00208     }
00209 
00210     prof_loop() {
00211         void *e = equeue_alloc(&q, 0);
00212 
00213         prof_start();
00214         int id = equeue_post(&q, no_func, e);
00215         prof_stop();
00216 
00217         equeue_cancel(&q, id);
00218     }
00219 
00220     equeue_destroy(&q);
00221 }
00222 
00223 void equeue_post_future_prof(void)
00224 {
00225     struct equeue q;
00226     equeue_create(&q, EQUEUE_EVENT_SIZE);
00227 
00228     prof_loop() {
00229         void *e = equeue_alloc(&q, 0);
00230         equeue_event_delay(e, 1000);
00231 
00232         prof_start();
00233         int id = equeue_post(&q, no_func, e);
00234         prof_stop();
00235 
00236         equeue_cancel(&q, id);
00237     }
00238 
00239     equeue_destroy(&q);
00240 }
00241 
00242 void equeue_post_future_many_prof(int count)
00243 {
00244     struct equeue q;
00245     equeue_create(&q, count * EQUEUE_EVENT_SIZE);
00246 
00247     for (int i = 0; i < count - 1; i++) {
00248         equeue_call(&q, no_func, 0);
00249     }
00250 
00251     prof_loop() {
00252         void *e = equeue_alloc(&q, 0);
00253         equeue_event_delay(e, 1000);
00254 
00255         prof_start();
00256         int id = equeue_post(&q, no_func, e);
00257         prof_stop();
00258 
00259         equeue_cancel(&q, id);
00260     }
00261 
00262     equeue_destroy(&q);
00263 }
00264 
00265 void equeue_dispatch_prof(void)
00266 {
00267     struct equeue q;
00268     equeue_create(&q, EQUEUE_EVENT_SIZE);
00269 
00270     prof_loop() {
00271         equeue_call(&q, no_func, 0);
00272 
00273         prof_start();
00274         equeue_dispatch(&q, 0);
00275         prof_stop();
00276     }
00277 
00278     equeue_destroy(&q);
00279 }
00280 
00281 void equeue_dispatch_many_prof(int count)
00282 {
00283     struct equeue q;
00284     equeue_create(&q, count * EQUEUE_EVENT_SIZE);
00285 
00286     prof_loop() {
00287         for (int i = 0; i < count; i++) {
00288             equeue_call(&q, no_func, 0);
00289         }
00290 
00291         prof_start();
00292         equeue_dispatch(&q, 0);
00293         prof_stop();
00294     }
00295 
00296     equeue_destroy(&q);
00297 }
00298 
00299 void equeue_cancel_prof(void)
00300 {
00301     struct equeue q;
00302     equeue_create(&q, EQUEUE_EVENT_SIZE);
00303 
00304     prof_loop() {
00305         int id = equeue_call(&q, no_func, 0);
00306 
00307         prof_start();
00308         equeue_cancel(&q, id);
00309         prof_stop();
00310     }
00311 
00312     equeue_destroy(&q);
00313 }
00314 
00315 void equeue_cancel_many_prof(int count)
00316 {
00317     struct equeue q;
00318     equeue_create(&q, count * EQUEUE_EVENT_SIZE);
00319 
00320     for (int i = 0; i < count - 1; i++) {
00321         equeue_call(&q, no_func, 0);
00322     }
00323 
00324     prof_loop() {
00325         int id = equeue_call(&q, no_func, 0);
00326 
00327         prof_start();
00328         equeue_cancel(&q, id);
00329         prof_stop();
00330     }
00331 
00332     equeue_destroy(&q);
00333 }
00334 
00335 void equeue_alloc_size_prof(void)
00336 {
00337     size_t size = 32 * EQUEUE_EVENT_SIZE;
00338 
00339     struct equeue q;
00340     equeue_create(&q, size);
00341     equeue_alloc(&q, 0);
00342 
00343     prof_result(size - q.slab.size, "bytes");
00344 
00345     equeue_destroy(&q);
00346 }
00347 
00348 void equeue_alloc_many_size_prof(int count)
00349 {
00350     size_t size = count * EQUEUE_EVENT_SIZE;
00351 
00352     struct equeue q;
00353     equeue_create(&q, size);
00354 
00355     for (int i = 0; i < count; i++) {
00356         equeue_alloc(&q, (i % 4) * sizeof(int));
00357     }
00358 
00359     prof_result(size - q.slab.size, "bytes");
00360 
00361     equeue_destroy(&q);
00362 }
00363 
00364 void equeue_alloc_fragmented_size_prof(int count)
00365 {
00366     size_t size = count * EQUEUE_EVENT_SIZE;
00367 
00368     struct equeue q;
00369     equeue_create(&q, size);
00370 
00371     void *es[count];
00372 
00373     for (int i = 0; i < count; i++) {
00374         es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
00375     }
00376 
00377     for (int i = 0; i < count; i++) {
00378         equeue_dealloc(&q, es[i]);
00379     }
00380 
00381     for (int i = count - 1; i >= 0; i--) {
00382         es[i] = equeue_alloc(&q, (i % 4) * sizeof(int));
00383     }
00384 
00385     for (int i = count - 1; i >= 0; i--) {
00386         equeue_dealloc(&q, es[i]);
00387     }
00388 
00389     for (int i = 0; i < count; i++) {
00390         equeue_alloc(&q, (i % 4) * sizeof(int));
00391     }
00392 
00393     prof_result(size - q.slab.size, "bytes");
00394 
00395     equeue_destroy(&q);
00396 }
00397 
00398 
00399 // Entry point
00400 int main()
00401 {
00402     printf("beginning profiling...\n");
00403 
00404     prof_baseline(baseline_prof);
00405 
00406     prof_measure(equeue_tick_prof);
00407     prof_measure(equeue_alloc_prof);
00408     prof_measure(equeue_post_prof);
00409     prof_measure(equeue_post_future_prof);
00410     prof_measure(equeue_dispatch_prof);
00411     prof_measure(equeue_cancel_prof);
00412 
00413     prof_measure(equeue_alloc_many_prof, 1000);
00414     prof_measure(equeue_post_many_prof, 1000);
00415     prof_measure(equeue_post_future_many_prof, 1000);
00416     prof_measure(equeue_dispatch_many_prof, 100);
00417     prof_measure(equeue_cancel_many_prof, 100);
00418 
00419     prof_measure(equeue_alloc_size_prof);
00420     prof_measure(equeue_alloc_many_size_prof, 1000);
00421     prof_measure(equeue_alloc_fragmented_size_prof, 1000);
00422 
00423     printf("done!\n");
00424 }