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 /src | |
| parent | ce56157e5f8ab1b244a63faf2e09ab8cd7c5ee23 (diff) | |
| download | emacs-12b3895d742e06ba3999773f0f02328ae7d9880f.tar.gz emacs-12b3895d742e06ba3999773f0f02328ae7d9880f.zip | |
Add GC profiler.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 53 | ||||
| -rw-r--r-- | src/lisp.h | 14 | ||||
| -rw-r--r-- | src/profiler.c | 49 |
3 files changed, 89 insertions, 27 deletions
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; |