diff options
| author | Paul Eggert | 2019-02-18 14:42:45 -0800 |
|---|---|---|
| committer | Paul Eggert | 2019-02-18 14:43:19 -0800 |
| commit | 5d46862440af7957ea617e42d6c1c6ee4c46ba3e (patch) | |
| tree | 9209c481866ae0c4bee67332cea8bd8b50e0d6ab /src | |
| parent | e6f8ddbb3b8f99c73b2be66bb1e691d4757c3b12 (diff) | |
| download | emacs-5d46862440af7957ea617e42d6c1c6ee4c46ba3e.tar.gz emacs-5d46862440af7957ea617e42d6c1c6ee4c46ba3e.zip | |
Minor profiler improvements
* src/profiler.c (evict_lower_half, record_backtrace)
(setup_cpu_timer, cmpfn_profiler, hashfn_profiler):
Assume C99. Use bool for boolean.
(timer_getoverrun): Remove; simplify use to not need it.
(Fprofiler_cpu_start): Any negative return from setup_cpu_timer fails.
(Fprofiler_cpu_stop): Simplify initialization.
Diffstat (limited to 'src')
| -rw-r--r-- | src/profiler.c | 50 |
1 files changed, 18 insertions, 32 deletions
diff --git a/src/profiler.c b/src/profiler.c index 293e52633a8..2aa5f345740 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -118,9 +118,8 @@ static void evict_lower_half (log_t *log) | |||
| 118 | { | 118 | { |
| 119 | ptrdiff_t size = ASIZE (log->key_and_value) / 2; | 119 | ptrdiff_t size = ASIZE (log->key_and_value) / 2; |
| 120 | EMACS_INT median = approximate_median (log, 0, size); | 120 | EMACS_INT median = approximate_median (log, 0, size); |
| 121 | ptrdiff_t i; | ||
| 122 | 121 | ||
| 123 | for (i = 0; i < size; i++) | 122 | for (ptrdiff_t i = 0; i < size; i++) |
| 124 | /* Evict not only values smaller but also values equal to the median, | 123 | /* Evict not only values smaller but also values equal to the median, |
| 125 | so as to make sure we evict something no matter what. */ | 124 | so as to make sure we evict something no matter what. */ |
| 126 | if (XFIXNUM (HASH_VALUE (log, i)) <= median) | 125 | if (XFIXNUM (HASH_VALUE (log, i)) <= median) |
| @@ -148,17 +147,14 @@ static void evict_lower_half (log_t *log) | |||
| 148 | static void | 147 | static void |
| 149 | record_backtrace (log_t *log, EMACS_INT count) | 148 | record_backtrace (log_t *log, EMACS_INT count) |
| 150 | { | 149 | { |
| 151 | Lisp_Object backtrace; | ||
| 152 | ptrdiff_t index; | ||
| 153 | |||
| 154 | if (log->next_free < 0) | 150 | if (log->next_free < 0) |
| 155 | /* FIXME: transfer the evicted counts to a special entry rather | 151 | /* FIXME: transfer the evicted counts to a special entry rather |
| 156 | than dropping them on the floor. */ | 152 | than dropping them on the floor. */ |
| 157 | evict_lower_half (log); | 153 | evict_lower_half (log); |
| 158 | index = log->next_free; | 154 | ptrdiff_t index = log->next_free; |
| 159 | 155 | ||
| 160 | /* Get a "working memory" vector. */ | 156 | /* Get a "working memory" vector. */ |
| 161 | backtrace = HASH_KEY (log, index); | 157 | Lisp_Object backtrace = HASH_KEY (log, index); |
| 162 | get_backtrace (backtrace); | 158 | get_backtrace (backtrace); |
| 163 | 159 | ||
| 164 | { /* We basically do a `gethash+puthash' here, except that we have to be | 160 | { /* We basically do a `gethash+puthash' here, except that we have to be |
| @@ -232,13 +228,6 @@ static EMACS_INT current_sampling_interval; | |||
| 232 | 228 | ||
| 233 | /* Signal handler for sampling profiler. */ | 229 | /* Signal handler for sampling profiler. */ |
| 234 | 230 | ||
| 235 | /* timer_getoverrun is not implemented on Cygwin prior to | ||
| 236 | cygwin-3.0.0, but the following seems to be good enough for | ||
| 237 | profiling. */ | ||
| 238 | #if defined CYGWIN && !defined HAVE_TIMER_GETOVERRUN | ||
| 239 | #define timer_getoverrun(x) 0 | ||
| 240 | #endif | ||
| 241 | |||
| 242 | static void | 231 | static void |
| 243 | handle_profiler_signal (int signal) | 232 | handle_profiler_signal (int signal) |
| 244 | { | 233 | { |
| @@ -253,7 +242,7 @@ handle_profiler_signal (int signal) | |||
| 253 | else | 242 | else |
| 254 | { | 243 | { |
| 255 | EMACS_INT count = 1; | 244 | EMACS_INT count = 1; |
| 256 | #ifdef HAVE_ITIMERSPEC | 245 | #if defined HAVE_ITIMERSPEC && defined HAVE_TIMER_GETOVERRUN |
| 257 | if (profiler_timer_ok) | 246 | if (profiler_timer_ok) |
| 258 | { | 247 | { |
| 259 | int overruns = timer_getoverrun (profiler_timer); | 248 | int overruns = timer_getoverrun (profiler_timer); |
| @@ -275,9 +264,6 @@ deliver_profiler_signal (int signal) | |||
| 275 | static int | 264 | static int |
| 276 | setup_cpu_timer (Lisp_Object sampling_interval) | 265 | setup_cpu_timer (Lisp_Object sampling_interval) |
| 277 | { | 266 | { |
| 278 | struct sigaction action; | ||
| 279 | struct itimerval timer; | ||
| 280 | struct timespec interval; | ||
| 281 | int billion = 1000000000; | 267 | int billion = 1000000000; |
| 282 | 268 | ||
| 283 | if (! RANGED_FIXNUMP (1, sampling_interval, | 269 | if (! RANGED_FIXNUMP (1, sampling_interval, |
| @@ -288,8 +274,10 @@ setup_cpu_timer (Lisp_Object sampling_interval) | |||
| 288 | return -1; | 274 | return -1; |
| 289 | 275 | ||
| 290 | current_sampling_interval = XFIXNUM (sampling_interval); | 276 | current_sampling_interval = XFIXNUM (sampling_interval); |
| 291 | interval = make_timespec (current_sampling_interval / billion, | 277 | struct timespec interval |
| 292 | current_sampling_interval % billion); | 278 | = make_timespec (current_sampling_interval / billion, |
| 279 | current_sampling_interval % billion); | ||
| 280 | struct sigaction action; | ||
| 293 | emacs_sigaction_init (&action, deliver_profiler_signal); | 281 | emacs_sigaction_init (&action, deliver_profiler_signal); |
| 294 | sigaction (SIGPROF, &action, 0); | 282 | sigaction (SIGPROF, &action, 0); |
| 295 | 283 | ||
| @@ -309,16 +297,15 @@ setup_cpu_timer (Lisp_Object sampling_interval) | |||
| 309 | #endif | 297 | #endif |
| 310 | CLOCK_REALTIME | 298 | CLOCK_REALTIME |
| 311 | }; | 299 | }; |
| 312 | int i; | ||
| 313 | struct sigevent sigev; | 300 | struct sigevent sigev; |
| 314 | sigev.sigev_value.sival_ptr = &profiler_timer; | 301 | sigev.sigev_value.sival_ptr = &profiler_timer; |
| 315 | sigev.sigev_signo = SIGPROF; | 302 | sigev.sigev_signo = SIGPROF; |
| 316 | sigev.sigev_notify = SIGEV_SIGNAL; | 303 | sigev.sigev_notify = SIGEV_SIGNAL; |
| 317 | 304 | ||
| 318 | for (i = 0; i < ARRAYELTS (system_clock); i++) | 305 | for (int i = 0; i < ARRAYELTS (system_clock); i++) |
| 319 | if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) | 306 | if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) |
| 320 | { | 307 | { |
| 321 | profiler_timer_ok = 1; | 308 | profiler_timer_ok = true; |
| 322 | break; | 309 | break; |
| 323 | } | 310 | } |
| 324 | } | 311 | } |
| @@ -333,6 +320,7 @@ setup_cpu_timer (Lisp_Object sampling_interval) | |||
| 333 | #endif | 320 | #endif |
| 334 | 321 | ||
| 335 | #ifdef HAVE_SETITIMER | 322 | #ifdef HAVE_SETITIMER |
| 323 | struct itimerval timer; | ||
| 336 | timer.it_value = timer.it_interval = make_timeval (interval); | 324 | timer.it_value = timer.it_interval = make_timeval (interval); |
| 337 | if (setitimer (ITIMER_PROF, &timer, 0) == 0) | 325 | if (setitimer (ITIMER_PROF, &timer, 0) == 0) |
| 338 | return SETITIMER_RUNNING; | 326 | return SETITIMER_RUNNING; |
| @@ -359,7 +347,7 @@ See also `profiler-log-size' and `profiler-max-stack-depth'. */) | |||
| 359 | } | 347 | } |
| 360 | 348 | ||
| 361 | int status = setup_cpu_timer (sampling_interval); | 349 | int status = setup_cpu_timer (sampling_interval); |
| 362 | if (status == -1) | 350 | if (status < 0) |
| 363 | { | 351 | { |
| 364 | profiler_cpu_running = NOT_RUNNING; | 352 | profiler_cpu_running = NOT_RUNNING; |
| 365 | error ("Invalid sampling interval"); | 353 | error ("Invalid sampling interval"); |
| @@ -388,8 +376,7 @@ Return non-nil if the profiler was running. */) | |||
| 388 | #ifdef HAVE_ITIMERSPEC | 376 | #ifdef HAVE_ITIMERSPEC |
| 389 | case TIMER_SETTIME_RUNNING: | 377 | case TIMER_SETTIME_RUNNING: |
| 390 | { | 378 | { |
| 391 | struct itimerspec disable; | 379 | struct itimerspec disable = { 0, }; |
| 392 | memset (&disable, 0, sizeof disable); | ||
| 393 | timer_settime (profiler_timer, 0, &disable, 0); | 380 | timer_settime (profiler_timer, 0, &disable, 0); |
| 394 | } | 381 | } |
| 395 | break; | 382 | break; |
| @@ -398,8 +385,7 @@ Return non-nil if the profiler was running. */) | |||
| 398 | #ifdef HAVE_SETITIMER | 385 | #ifdef HAVE_SETITIMER |
| 399 | case SETITIMER_RUNNING: | 386 | case SETITIMER_RUNNING: |
| 400 | { | 387 | { |
| 401 | struct itimerval disable; | 388 | struct itimerval disable = { 0, }; |
| 402 | memset (&disable, 0, sizeof disable); | ||
| 403 | setitimer (ITIMER_PROF, &disable, 0); | 389 | setitimer (ITIMER_PROF, &disable, 0); |
| 404 | } | 390 | } |
| 405 | break; | 391 | break; |
| @@ -551,10 +537,10 @@ cmpfn_profiler (struct hash_table_test *t, | |||
| 551 | { | 537 | { |
| 552 | if (VECTORP (bt1) && VECTORP (bt2)) | 538 | if (VECTORP (bt1) && VECTORP (bt2)) |
| 553 | { | 539 | { |
| 554 | ptrdiff_t i, l = ASIZE (bt1); | 540 | ptrdiff_t l = ASIZE (bt1); |
| 555 | if (l != ASIZE (bt2)) | 541 | if (l != ASIZE (bt2)) |
| 556 | return false; | 542 | return false; |
| 557 | for (i = 0; i < l; i++) | 543 | for (ptrdiff_t i = 0; i < l; i++) |
| 558 | if (NILP (Ffunction_equal (AREF (bt1, i), AREF (bt2, i)))) | 544 | if (NILP (Ffunction_equal (AREF (bt1, i), AREF (bt2, i)))) |
| 559 | return false; | 545 | return false; |
| 560 | return true; | 546 | return true; |
| @@ -569,8 +555,8 @@ hashfn_profiler (struct hash_table_test *ht, Lisp_Object bt) | |||
| 569 | if (VECTORP (bt)) | 555 | if (VECTORP (bt)) |
| 570 | { | 556 | { |
| 571 | EMACS_UINT hash = 0; | 557 | EMACS_UINT hash = 0; |
| 572 | ptrdiff_t i, l = ASIZE (bt); | 558 | ptrdiff_t l = ASIZE (bt); |
| 573 | for (i = 0; i < l; i++) | 559 | for (ptrdiff_t i = 0; i < l; i++) |
| 574 | { | 560 | { |
| 575 | Lisp_Object f = AREF (bt, i); | 561 | Lisp_Object f = AREF (bt, i); |
| 576 | EMACS_UINT hash1 | 562 | EMACS_UINT hash1 |