diff options
| author | Tomohiro Matsuyama | 2012-08-22 21:38:39 +0900 |
|---|---|---|
| committer | Tomohiro Matsuyama | 2012-08-22 21:38:39 +0900 |
| commit | 12b3895d742e06ba3999773f0f02328ae7d9880f (patch) | |
| tree | 892a7d66df4967c2682804bac5fa7df5cea0581f | |
| parent | ce56157e5f8ab1b244a63faf2e09ab8cd7c5ee23 (diff) | |
| download | emacs-12b3895d742e06ba3999773f0f02328ae7d9880f.tar.gz emacs-12b3895d742e06ba3999773f0f02328ae7d9880f.zip | |
Add GC profiler.
| -rw-r--r-- | lisp/profiler.el | 91 | ||||
| -rw-r--r-- | src/alloc.c | 53 | ||||
| -rw-r--r-- | src/lisp.h | 14 | ||||
| -rw-r--r-- | src/profiler.c | 49 |
4 files changed, 157 insertions, 50 deletions
diff --git a/lisp/profiler.el b/lisp/profiler.el index 9e94f0d078c..3f10735ccba 100644 --- a/lisp/profiler.el +++ b/lisp/profiler.el | |||
| @@ -44,10 +44,16 @@ | |||
| 44 | (defun profiler-format (fmt &rest args) | 44 | (defun profiler-format (fmt &rest args) |
| 45 | (cl-loop for (width align subfmt) in fmt | 45 | (cl-loop for (width align subfmt) in fmt |
| 46 | for arg in args | 46 | for arg in args |
| 47 | for str = (cl-typecase subfmt | 47 | for str = (cond |
| 48 | (cons (apply 'profiler-format subfmt arg)) | 48 | ((consp subfmt) |
| 49 | (string (format subfmt arg)) | 49 | (apply 'profiler-format subfmt arg)) |
| 50 | (t (profiler-ensure-string arg))) | 50 | ((stringp subfmt) |
| 51 | (format subfmt arg)) | ||
| 52 | ((and (symbolp subfmt) | ||
| 53 | (fboundp subfmt)) | ||
| 54 | (funcall subfmt arg)) | ||
| 55 | (t | ||
| 56 | (profiler-ensure-string arg))) | ||
| 51 | for len = (length str) | 57 | for len = (length str) |
| 52 | if (< width len) | 58 | if (< width len) |
| 53 | collect (substring str 0 width) into frags | 59 | collect (substring str 0 width) into frags |
| @@ -60,6 +66,30 @@ | |||
| 60 | into frags | 66 | into frags |
| 61 | finally return (apply #'concat frags))) | 67 | finally return (apply #'concat frags))) |
| 62 | 68 | ||
| 69 | (defun profiler-format-nbytes (nbytes) | ||
| 70 | (if (and (integerp nbytes) (> nbytes 0)) | ||
| 71 | (cl-loop with i = (% (1+ (floor (log10 nbytes))) 3) | ||
| 72 | for c in (append (number-to-string nbytes) nil) | ||
| 73 | if (= i 0) | ||
| 74 | collect ?, into s | ||
| 75 | and do (setq i 3) | ||
| 76 | collect c into s | ||
| 77 | do (cl-decf i) | ||
| 78 | finally return | ||
| 79 | (apply 'string (if (eq (car s) ?,) (cdr s) s))) | ||
| 80 | (profiler-ensure-string nbytes))) | ||
| 81 | |||
| 82 | |||
| 83 | |||
| 84 | ;;; Backtrace data structure | ||
| 85 | |||
| 86 | (defun profiler-backtrace-reverse (backtrace) | ||
| 87 | (cl-case (car backtrace) | ||
| 88 | ((t gc) | ||
| 89 | (cons (car backtrace) | ||
| 90 | (reverse (cdr backtrace)))) | ||
| 91 | (t (reverse backtrace)))) | ||
| 92 | |||
| 63 | 93 | ||
| 64 | 94 | ||
| 65 | ;;; Slot data structure | 95 | ;;; Slot data structure |
| @@ -105,7 +135,7 @@ | |||
| 105 | (format "#<compiled 0x%x>" (sxhash entry))) | 135 | (format "#<compiled 0x%x>" (sxhash entry))) |
| 106 | ((subrp entry) | 136 | ((subrp entry) |
| 107 | (subr-name entry)) | 137 | (subr-name entry)) |
| 108 | ((symbolp entry) | 138 | ((or (symbolp entry) (stringp entry)) |
| 109 | entry) | 139 | entry) |
| 110 | (t | 140 | (t |
| 111 | (format "#<unknown 0x%x>" (sxhash entry))))))) | 141 | (format "#<unknown 0x%x>" (sxhash entry))))))) |
| @@ -129,6 +159,8 @@ | |||
| 129 | (defun profiler-calltree-count< (a b) | 159 | (defun profiler-calltree-count< (a b) |
| 130 | (cond ((eq (profiler-calltree-entry a) t) t) | 160 | (cond ((eq (profiler-calltree-entry a) t) t) |
| 131 | ((eq (profiler-calltree-entry b) t) nil) | 161 | ((eq (profiler-calltree-entry b) t) nil) |
| 162 | ((eq (profiler-calltree-entry a) 'gc) t) | ||
| 163 | ((eq (profiler-calltree-entry b) 'gc) nil) | ||
| 132 | (t (< (profiler-calltree-count a) | 164 | (t (< (profiler-calltree-count a) |
| 133 | (profiler-calltree-count b))))) | 165 | (profiler-calltree-count b))))) |
| 134 | 166 | ||
| @@ -138,6 +170,8 @@ | |||
| 138 | (defun profiler-calltree-elapsed< (a b) | 170 | (defun profiler-calltree-elapsed< (a b) |
| 139 | (cond ((eq (profiler-calltree-entry a) t) t) | 171 | (cond ((eq (profiler-calltree-entry a) t) t) |
| 140 | ((eq (profiler-calltree-entry b) t) nil) | 172 | ((eq (profiler-calltree-entry b) t) nil) |
| 173 | ((eq (profiler-calltree-entry a) 'gc) t) | ||
| 174 | ((eq (profiler-calltree-entry b) 'gc) nil) | ||
| 141 | (t (< (profiler-calltree-elapsed a) | 175 | (t (< (profiler-calltree-elapsed a) |
| 142 | (profiler-calltree-elapsed b))))) | 176 | (profiler-calltree-elapsed b))))) |
| 143 | 177 | ||
| @@ -166,7 +200,9 @@ | |||
| 166 | (count (profiler-slot-count slot)) | 200 | (count (profiler-slot-count slot)) |
| 167 | (elapsed (profiler-slot-elapsed slot)) | 201 | (elapsed (profiler-slot-elapsed slot)) |
| 168 | (node tree)) | 202 | (node tree)) |
| 169 | (dolist (entry (if reverse backtrace (reverse backtrace))) | 203 | (dolist (entry (if reverse |
| 204 | backtrace | ||
| 205 | (profiler-backtrace-reverse backtrace))) | ||
| 170 | (let ((child (profiler-calltree-find node entry))) | 206 | (let ((child (profiler-calltree-find node entry))) |
| 171 | (unless child | 207 | (unless child |
| 172 | (setq child (profiler-make-calltree :entry entry :parent node)) | 208 | (setq child (profiler-make-calltree :entry entry :parent node)) |
| @@ -179,20 +215,27 @@ | |||
| 179 | (let ((total-count 0) | 215 | (let ((total-count 0) |
| 180 | (total-elapsed 0)) | 216 | (total-elapsed 0)) |
| 181 | (dolist (child (profiler-calltree-children tree)) | 217 | (dolist (child (profiler-calltree-children tree)) |
| 182 | (cl-incf total-count (profiler-calltree-count child)) | 218 | (if (eq (profiler-calltree-entry child) 'gc) |
| 183 | (cl-incf total-elapsed (profiler-calltree-elapsed child))) | 219 | (profiler-calltree-compute-percentages child) |
| 184 | (profiler-calltree-walk | 220 | (cl-incf total-count (profiler-calltree-count child)) |
| 185 | tree (lambda (node) | 221 | (cl-incf total-elapsed (profiler-calltree-elapsed child)))) |
| 186 | (unless (zerop total-count) | 222 | (dolist (child (profiler-calltree-children tree)) |
| 187 | (setf (profiler-calltree-count-percent node) | 223 | (if (eq (profiler-calltree-entry child) 'gc) |
| 188 | (format "%s%%" | 224 | (setf (profiler-calltree-count-percent child) "" |
| 189 | (/ (* (profiler-calltree-count node) 100) | 225 | (profiler-calltree-elapsed-percent child) "") |
| 190 | total-count)))) | 226 | (profiler-calltree-walk |
| 191 | (unless (zerop total-elapsed) | 227 | child |
| 192 | (setf (profiler-calltree-elapsed-percent node) | 228 | (lambda (node) |
| 193 | (format "%s%%" | 229 | (unless (zerop total-count) |
| 194 | (/ (* (profiler-calltree-elapsed node) 100) | 230 | (setf (profiler-calltree-count-percent node) |
| 195 | total-elapsed)))))))) | 231 | (format "%s%%" |
| 232 | (/ (* (profiler-calltree-count node) 100) | ||
| 233 | total-count)))) | ||
| 234 | (unless (zerop total-elapsed) | ||
| 235 | (setf (profiler-calltree-elapsed-percent node) | ||
| 236 | (format "%s%%" | ||
| 237 | (/ (* (profiler-calltree-elapsed node) 100) | ||
| 238 | total-elapsed)))))))))) | ||
| 196 | 239 | ||
| 197 | (cl-defun profiler-calltree-build (log &key reverse) | 240 | (cl-defun profiler-calltree-build (log &key reverse) |
| 198 | (let ((tree (profiler-make-calltree))) | 241 | (let ((tree (profiler-make-calltree))) |
| @@ -231,8 +274,8 @@ | |||
| 231 | (5 right))))) | 274 | (5 right))))) |
| 232 | 275 | ||
| 233 | (defvar profiler-report-memory-line-format | 276 | (defvar profiler-report-memory-line-format |
| 234 | '((60 left) | 277 | '((55 left) |
| 235 | (14 right ((9 right) | 278 | (19 right ((14 right profiler-format-nbytes) |
| 236 | (5 right))))) | 279 | (5 right))))) |
| 237 | 280 | ||
| 238 | (defvar profiler-report-log nil) | 281 | (defvar profiler-report-log nil) |
| @@ -244,6 +287,8 @@ | |||
| 244 | (cond | 287 | (cond |
| 245 | ((eq entry t) | 288 | ((eq entry t) |
| 246 | "Others") | 289 | "Others") |
| 290 | ((eq entry 'gc) | ||
| 291 | "Garbage Collection") | ||
| 247 | ((and (symbolp entry) | 292 | ((and (symbolp entry) |
| 248 | (fboundp entry)) | 293 | (fboundp entry)) |
| 249 | (propertize (symbol-name entry) | 294 | (propertize (symbol-name entry) |
| @@ -462,7 +507,7 @@ otherwise collapse the entry." | |||
| 462 | (setq header-line-format | 507 | (setq header-line-format |
| 463 | (profiler-report-header-line-format | 508 | (profiler-report-header-line-format |
| 464 | profiler-report-memory-line-format | 509 | profiler-report-memory-line-format |
| 465 | "Function" (list "Alloc" "%"))) | 510 | "Function" (list "Bytes" "%"))) |
| 466 | (let ((predicate (cl-ecase order | 511 | (let ((predicate (cl-ecase order |
| 467 | (ascending 'profiler-calltree-count<) | 512 | (ascending 'profiler-calltree-count<) |
| 468 | (descending 'profiler-calltree-count>)))) | 513 | (descending 'profiler-calltree-count>)))) |
diff --git a/src/alloc.c b/src/alloc.c index 3a4a8de90f5..389da29a533 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5380,6 +5380,23 @@ bounded_number (EMACS_INT number) | |||
| 5380 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); | 5380 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); |
| 5381 | } | 5381 | } |
| 5382 | 5382 | ||
| 5383 | /* Calculate total bytes of live objects. */ | ||
| 5384 | |||
| 5385 | static size_t | ||
| 5386 | total_bytes_of_live_objects (void) | ||
| 5387 | { | ||
| 5388 | size_t tot = 0; | ||
| 5389 | tot += total_conses * sizeof (struct Lisp_Cons); | ||
| 5390 | tot += total_symbols * sizeof (struct Lisp_Symbol); | ||
| 5391 | tot += total_markers * sizeof (union Lisp_Misc); | ||
| 5392 | tot += total_string_bytes; | ||
| 5393 | tot += total_vector_slots * word_size; | ||
| 5394 | tot += total_floats * sizeof (struct Lisp_Float); | ||
| 5395 | tot += total_intervals * sizeof (struct interval); | ||
| 5396 | tot += total_strings * sizeof (struct Lisp_String); | ||
| 5397 | return tot; | ||
| 5398 | } | ||
| 5399 | |||
| 5383 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5400 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5384 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5401 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5385 | Garbage collection happens automatically if you cons more than | 5402 | Garbage collection happens automatically if you cons more than |
| @@ -5405,6 +5422,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5405 | ptrdiff_t count = SPECPDL_INDEX (); | 5422 | ptrdiff_t count = SPECPDL_INDEX (); |
| 5406 | EMACS_TIME start; | 5423 | EMACS_TIME start; |
| 5407 | Lisp_Object retval = Qnil; | 5424 | Lisp_Object retval = Qnil; |
| 5425 | size_t tot_before = 0; | ||
| 5408 | 5426 | ||
| 5409 | if (abort_on_gc) | 5427 | if (abort_on_gc) |
| 5410 | abort (); | 5428 | abort (); |
| @@ -5421,6 +5439,9 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5421 | FOR_EACH_BUFFER (nextb) | 5439 | FOR_EACH_BUFFER (nextb) |
| 5422 | compact_buffer (nextb); | 5440 | compact_buffer (nextb); |
| 5423 | 5441 | ||
| 5442 | if (memory_profiler_running) | ||
| 5443 | tot_before = total_bytes_of_live_objects (); | ||
| 5444 | |||
| 5424 | start = current_emacs_time (); | 5445 | start = current_emacs_time (); |
| 5425 | 5446 | ||
| 5426 | /* In case user calls debug_print during GC, | 5447 | /* In case user calls debug_print during GC, |
| @@ -5467,6 +5488,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5467 | shrink_regexp_cache (); | 5488 | shrink_regexp_cache (); |
| 5468 | 5489 | ||
| 5469 | gc_in_progress = 1; | 5490 | gc_in_progress = 1; |
| 5491 | is_in_trace = 1; | ||
| 5470 | 5492 | ||
| 5471 | /* Mark all the special slots that serve as the roots of accessibility. */ | 5493 | /* Mark all the special slots that serve as the roots of accessibility. */ |
| 5472 | 5494 | ||
| @@ -5587,6 +5609,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5587 | check_cons_list (); | 5609 | check_cons_list (); |
| 5588 | 5610 | ||
| 5589 | gc_in_progress = 0; | 5611 | gc_in_progress = 0; |
| 5612 | is_in_trace = 0; | ||
| 5590 | 5613 | ||
| 5591 | consing_since_gc = 0; | 5614 | consing_since_gc = 0; |
| 5592 | if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) | 5615 | if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) |
| @@ -5595,16 +5618,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5595 | gc_relative_threshold = 0; | 5618 | gc_relative_threshold = 0; |
| 5596 | if (FLOATP (Vgc_cons_percentage)) | 5619 | if (FLOATP (Vgc_cons_percentage)) |
| 5597 | { /* Set gc_cons_combined_threshold. */ | 5620 | { /* Set gc_cons_combined_threshold. */ |
| 5598 | double tot = 0; | 5621 | double tot = total_bytes_of_live_objects (); |
| 5599 | |||
| 5600 | tot += total_conses * sizeof (struct Lisp_Cons); | ||
| 5601 | tot += total_symbols * sizeof (struct Lisp_Symbol); | ||
| 5602 | tot += total_markers * sizeof (union Lisp_Misc); | ||
| 5603 | tot += total_string_bytes; | ||
| 5604 | tot += total_vector_slots * word_size; | ||
| 5605 | tot += total_floats * sizeof (struct Lisp_Float); | ||
| 5606 | tot += total_intervals * sizeof (struct interval); | ||
| 5607 | tot += total_strings * sizeof (struct Lisp_String); | ||
| 5608 | 5622 | ||
| 5609 | tot *= XFLOAT_DATA (Vgc_cons_percentage); | 5623 | tot *= XFLOAT_DATA (Vgc_cons_percentage); |
| 5610 | if (0 < tot) | 5624 | if (0 < tot) |
| @@ -5707,6 +5721,25 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5707 | 5721 | ||
| 5708 | gcs_done++; | 5722 | gcs_done++; |
| 5709 | 5723 | ||
| 5724 | /* Collect profiling data. */ | ||
| 5725 | if (sample_profiler_running || memory_profiler_running) | ||
| 5726 | { | ||
| 5727 | size_t swept = 0; | ||
| 5728 | size_t elapsed = 0; | ||
| 5729 | if (memory_profiler_running) | ||
| 5730 | { | ||
| 5731 | size_t tot_after = total_bytes_of_live_objects (); | ||
| 5732 | if (tot_before > tot_after) | ||
| 5733 | swept = tot_before - tot_after; | ||
| 5734 | } | ||
| 5735 | if (sample_profiler_running) | ||
| 5736 | { | ||
| 5737 | EMACS_TIME since_start = sub_emacs_time (current_emacs_time (), start); | ||
| 5738 | elapsed = EMACS_TIME_TO_DOUBLE (since_start) * 1000; | ||
| 5739 | } | ||
| 5740 | gc_probe (swept, elapsed); | ||
| 5741 | } | ||
| 5742 | |||
| 5710 | return retval; | 5743 | return retval; |
| 5711 | } | 5744 | } |
| 5712 | 5745 | ||
diff --git a/src/lisp.h b/src/lisp.h index b4cead003c2..a979d45b49f 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3532,12 +3532,18 @@ void syms_of_dbusbind (void); | |||
| 3532 | /* Defined in profiler.c */ | 3532 | /* Defined in profiler.c */ |
| 3533 | extern int sample_profiler_running; | 3533 | extern int sample_profiler_running; |
| 3534 | extern int memory_profiler_running; | 3534 | extern int memory_profiler_running; |
| 3535 | extern int is_in_trace; | ||
| 3536 | extern Lisp_Object Qgc; | ||
| 3535 | extern void malloc_probe (size_t); | 3537 | extern void malloc_probe (size_t); |
| 3536 | #define MALLOC_PROBE(size) \ | 3538 | extern void gc_probe (size_t, size_t); |
| 3537 | do { \ | 3539 | #define ENTER_TRACE (is_in_trace = 1) |
| 3538 | if (memory_profiler_running) \ | 3540 | #define LEAVE_TRACE (is_in_trace = 0) |
| 3539 | malloc_probe (size); \ | 3541 | #define MALLOC_PROBE(size) \ |
| 3542 | do { \ | ||
| 3543 | if (memory_profiler_running) \ | ||
| 3544 | malloc_probe (size); \ | ||
| 3540 | } while (0) | 3545 | } while (0) |
| 3546 | |||
| 3541 | extern void mark_profiler (void); | 3547 | extern void mark_profiler (void); |
| 3542 | extern void syms_of_profiler (void); | 3548 | extern void syms_of_profiler (void); |
| 3543 | 3549 | ||
diff --git a/src/profiler.c b/src/profiler.c index 56458c64b85..c26761148df 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -25,6 +25,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 25 | #include <setjmp.h> | 25 | #include <setjmp.h> |
| 26 | #include "lisp.h" | 26 | #include "lisp.h" |
| 27 | 27 | ||
| 28 | int is_in_trace; | ||
| 29 | Lisp_Object Qgc; | ||
| 30 | |||
| 28 | static void sigprof_handler (int, siginfo_t *, void *); | 31 | static void sigprof_handler (int, siginfo_t *, void *); |
| 29 | static void block_sigprof (void); | 32 | static void block_sigprof (void); |
| 30 | static void unblock_sigprof (void); | 33 | static void unblock_sigprof (void); |
| @@ -350,8 +353,8 @@ struct slot | |||
| 350 | { | 353 | { |
| 351 | struct slot *next, *prev; | 354 | struct slot *next, *prev; |
| 352 | Lisp_Object backtrace; | 355 | Lisp_Object backtrace; |
| 353 | unsigned int count; | 356 | size_t count; |
| 354 | unsigned int elapsed; | 357 | size_t elapsed; |
| 355 | unsigned char used : 1; | 358 | unsigned char used : 1; |
| 356 | }; | 359 | }; |
| 357 | 360 | ||
| @@ -536,8 +539,8 @@ struct log | |||
| 536 | Lisp_Object backtrace; | 539 | Lisp_Object backtrace; |
| 537 | struct slot_heap *slot_heap; | 540 | struct slot_heap *slot_heap; |
| 538 | struct slot_table *slot_table; | 541 | struct slot_table *slot_table; |
| 539 | unsigned int others_count; | 542 | size_t others_count; |
| 540 | unsigned int others_elapsed; | 543 | size_t others_elapsed; |
| 541 | }; | 544 | }; |
| 542 | 545 | ||
| 543 | static struct log * | 546 | static struct log * |
| @@ -647,22 +650,23 @@ ensure_slot (struct log *log, Lisp_Object backtrace) | |||
| 647 | } | 650 | } |
| 648 | 651 | ||
| 649 | static void | 652 | static void |
| 650 | record_backtrace (struct log *log, unsigned int count, unsigned int elapsed) | 653 | record_backtrace_under (struct log *log, Lisp_Object base, |
| 654 | size_t count, size_t elapsed) | ||
| 651 | { | 655 | { |
| 652 | int i; | 656 | int i = 0; |
| 653 | Lisp_Object backtrace = log->backtrace; | 657 | Lisp_Object backtrace = log->backtrace; |
| 654 | struct backtrace *backlist = backtrace_list; | 658 | struct backtrace *backlist = backtrace_list; |
| 655 | 659 | ||
| 656 | if (!apply_filter (backlist)) return; | 660 | if (!apply_filter (backlist)) return; |
| 657 | 661 | ||
| 658 | for (i = 0; i < ASIZE (backtrace) && backlist; backlist = backlist->next) | 662 | if (!NILP (base) && ASIZE (backtrace) > 0) |
| 663 | ASET (backtrace, i++, base); | ||
| 664 | |||
| 665 | for (; i < ASIZE (backtrace) && backlist; backlist = backlist->next) | ||
| 659 | { | 666 | { |
| 660 | Lisp_Object function = *backlist->function; | 667 | Lisp_Object function = *backlist->function; |
| 661 | if (FUNCTIONP (function)) | 668 | if (FUNCTIONP (function)) |
| 662 | { | 669 | ASET (backtrace, i++, function); |
| 663 | ASET (backtrace, i, function); | ||
| 664 | i++; | ||
| 665 | } | ||
| 666 | } | 670 | } |
| 667 | for (; i < ASIZE (backtrace); i++) | 671 | for (; i < ASIZE (backtrace); i++) |
| 668 | ASET (backtrace, i, Qnil); | 672 | ASET (backtrace, i, Qnil); |
| @@ -675,6 +679,12 @@ record_backtrace (struct log *log, unsigned int count, unsigned int elapsed) | |||
| 675 | } | 679 | } |
| 676 | } | 680 | } |
| 677 | 681 | ||
| 682 | static void | ||
| 683 | record_backtrace (struct log *log, size_t count, size_t elapsed) | ||
| 684 | { | ||
| 685 | record_backtrace_under (log, Qnil, count, elapsed); | ||
| 686 | } | ||
| 687 | |||
| 678 | static Lisp_Object | 688 | static Lisp_Object |
| 679 | log_object (struct log *log) | 689 | log_object (struct log *log) |
| 680 | { | 690 | { |
| @@ -892,7 +902,8 @@ DEFUN ("memory-profiler-log", | |||
| 892 | static void | 902 | static void |
| 893 | sigprof_handler (int signal, siginfo_t *info, void *ctx) | 903 | sigprof_handler (int signal, siginfo_t *info, void *ctx) |
| 894 | { | 904 | { |
| 895 | record_backtrace (sample_log, 1, current_sample_interval); | 905 | if (!is_in_trace && sample_log) |
| 906 | record_backtrace (sample_log, 1, current_sample_interval); | ||
| 896 | } | 907 | } |
| 897 | 908 | ||
| 898 | static void | 909 | static void |
| @@ -916,7 +927,17 @@ unblock_sigprof (void) | |||
| 916 | void | 927 | void |
| 917 | malloc_probe (size_t size) | 928 | malloc_probe (size_t size) |
| 918 | { | 929 | { |
| 919 | record_backtrace (memory_log, size, 0); | 930 | if (memory_log) |
| 931 | record_backtrace (memory_log, size, 0); | ||
| 932 | } | ||
| 933 | |||
| 934 | void | ||
| 935 | gc_probe (size_t size, size_t elapsed) | ||
| 936 | { | ||
| 937 | if (sample_log) | ||
| 938 | record_backtrace_under (sample_log, Qgc, 1, elapsed); | ||
| 939 | if (memory_log) | ||
| 940 | record_backtrace_under (memory_log, Qgc, size, elapsed); | ||
| 920 | } | 941 | } |
| 921 | 942 | ||
| 922 | 943 | ||
| @@ -942,6 +963,8 @@ mark_profiler (void) | |||
| 942 | void | 963 | void |
| 943 | syms_of_profiler (void) | 964 | syms_of_profiler (void) |
| 944 | { | 965 | { |
| 966 | DEFSYM (Qgc, "gc"); | ||
| 967 | |||
| 945 | DEFVAR_INT ("profiler-max-stack-depth", profiler_max_stack_depth, | 968 | DEFVAR_INT ("profiler-max-stack-depth", profiler_max_stack_depth, |
| 946 | doc: /* FIXME */); | 969 | doc: /* FIXME */); |
| 947 | profiler_max_stack_depth = 16; | 970 | profiler_max_stack_depth = 16; |