aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTomohiro Matsuyama2012-08-22 21:38:39 +0900
committerTomohiro Matsuyama2012-08-22 21:38:39 +0900
commit12b3895d742e06ba3999773f0f02328ae7d9880f (patch)
tree892a7d66df4967c2682804bac5fa7df5cea0581f /src
parentce56157e5f8ab1b244a63faf2e09ab8cd7c5ee23 (diff)
downloademacs-12b3895d742e06ba3999773f0f02328ae7d9880f.tar.gz
emacs-12b3895d742e06ba3999773f0f02328ae7d9880f.zip
Add GC profiler.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c53
-rw-r--r--src/lisp.h14
-rw-r--r--src/profiler.c49
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
5385static size_t
5386total_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
5383DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 5400DEFUN ("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.
5385Garbage collection happens automatically if you cons more than 5402Garbage 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 */
3533extern int sample_profiler_running; 3533extern int sample_profiler_running;
3534extern int memory_profiler_running; 3534extern int memory_profiler_running;
3535extern int is_in_trace;
3536extern Lisp_Object Qgc;
3535extern void malloc_probe (size_t); 3537extern void malloc_probe (size_t);
3536#define MALLOC_PROBE(size) \ 3538extern 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
3541extern void mark_profiler (void); 3547extern void mark_profiler (void);
3542extern void syms_of_profiler (void); 3548extern 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
28int is_in_trace;
29Lisp_Object Qgc;
30
28static void sigprof_handler (int, siginfo_t *, void *); 31static void sigprof_handler (int, siginfo_t *, void *);
29static void block_sigprof (void); 32static void block_sigprof (void);
30static void unblock_sigprof (void); 33static 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
543static struct log * 546static struct log *
@@ -647,22 +650,23 @@ ensure_slot (struct log *log, Lisp_Object backtrace)
647} 650}
648 651
649static void 652static void
650record_backtrace (struct log *log, unsigned int count, unsigned int elapsed) 653record_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
682static void
683record_backtrace (struct log *log, size_t count, size_t elapsed)
684{
685 record_backtrace_under (log, Qnil, count, elapsed);
686}
687
678static Lisp_Object 688static Lisp_Object
679log_object (struct log *log) 689log_object (struct log *log)
680{ 690{
@@ -892,7 +902,8 @@ DEFUN ("memory-profiler-log",
892static void 902static void
893sigprof_handler (int signal, siginfo_t *info, void *ctx) 903sigprof_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
898static void 909static void
@@ -916,7 +927,17 @@ unblock_sigprof (void)
916void 927void
917malloc_probe (size_t size) 928malloc_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
934void
935gc_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)
942void 963void
943syms_of_profiler (void) 964syms_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;