diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2012-09-24 22:30:46 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2012-09-24 22:30:46 -0400 |
commit | 6521894d1aa5a1017dd6f3f55b5e7c11dde5d004 (patch) | |
tree | f74f3953cb1ff8905eb9e7b3e3cc39bae8edd18c /src/profiler.c | |
parent | ad942b63d7a9b984752f46bc2049fe10e488230d (diff) | |
download | emacs-6521894d1aa5a1017dd6f3f55b5e7c11dde5d004.tar.gz |
* src/profiler.c: Rename sample_profiler_* to profiler_cpu_* and
memory_profiler_* to profiler_memory_*. Move sigprof_handler before
its first use, inside the PROFILER_CPU_SUPPORT conditional.
Diffstat (limited to 'src/profiler.c')
-rw-r--r-- | src/profiler.c | 177 |
1 files changed, 89 insertions, 88 deletions
diff --git a/src/profiler.c b/src/profiler.c index d22ab14e7ce..1c4fa0fa218 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -25,17 +25,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <setjmp.h> #include "lisp.h" -/* True if sampling profiler is running. */ - -bool sample_profiler_running; - -/* True if memory profiler is running. */ - -bool memory_profiler_running; - -static void sigprof_handler (int, siginfo_t *, void *); - - /* Logs. */ typedef struct Lisp_Hash_Table log_t; @@ -193,6 +182,9 @@ record_backtrace (log_t *log, size_t count) #if defined SIGPROF && defined HAVE_SETITIMER #define PROFILER_CPU_SUPPORT +/* True if sampling profiler is running. */ +static bool profiler_cpu_running; + static Lisp_Object cpu_log; /* Separate counter for the time spent in the GC. */ static EMACS_INT cpu_gc_count; @@ -201,23 +193,41 @@ static EMACS_INT cpu_gc_count; static int current_sample_interval; -DEFUN ("sample-profiler-start", Fsample_profiler_start, Ssample_profiler_start, +/* Signal handler for sample profiler. */ + +static void +sigprof_handler (int signal, siginfo_t *info, void *ctx) +{ + eassert (HASH_TABLE_P (cpu_log)); + if (backtrace_list && EQ (*backtrace_list->function, Qautomatic_gc)) + /* Special case the time-count inside GC because the hash-table + code is not prepared to be used while the GC is running. + More specifically it uses ASIZE at many places where it does + not expect the ARRAY_MARK_FLAG to be set. We could try and + harden the hash-table code, but it doesn't seem worth the + effort. */ + cpu_gc_count += current_sample_interval; + else + record_backtrace (XHASH_TABLE (cpu_log), current_sample_interval); +} + +DEFUN ("profiler-cpu-start", Fprofiler_cpu_start, Sprofiler_cpu_start, 1, 1, 0, - doc: /* Start or restart sample profiler. Sample profiler will -take samples each SAMPLE-INTERVAL in millisecond. See also -`profiler-slot-heap-size' and `profiler-max-stack-depth'. */) + doc: /* Start or restart the cpu profiler. +The cpu profiler will take call-stack samples each SAMPLE-INTERVAL (expressed in milliseconds). +See also `profiler-log-size' and `profiler-max-stack-depth'. */) (Lisp_Object sample_interval) { struct sigaction sa; struct itimerval timer; - if (sample_profiler_running) + if (profiler_cpu_running) error ("Sample profiler is already running"); if (NILP (cpu_log)) { cpu_gc_count = 0; - cpu_log = make_log (profiler_slot_heap_size, + cpu_log = make_log (profiler_log_size, profiler_max_stack_depth); } @@ -233,48 +243,49 @@ take samples each SAMPLE-INTERVAL in millisecond. See also timer.it_value = timer.it_interval; setitimer (ITIMER_PROF, &timer, 0); - sample_profiler_running = 1; + profiler_cpu_running = 1; return Qt; } -DEFUN ("sample-profiler-stop", Fsample_profiler_stop, Ssample_profiler_stop, +DEFUN ("profiler-cpu-stop", Fprofiler_cpu_stop, Sprofiler_cpu_stop, 0, 0, 0, - doc: /* Stop sample profiler. Profiler log will be kept. */) + doc: /* Stop the cpu profiler. The profiler log is not affected. */) (void) { - if (!sample_profiler_running) + if (!profiler_cpu_running) error ("Sample profiler is not running"); - sample_profiler_running = 0; + profiler_cpu_running = 0; setitimer (ITIMER_PROF, 0, 0); return Qt; } -DEFUN ("sample-profiler-running-p", - Fsample_profiler_running_p, Ssample_profiler_running_p, +DEFUN ("profiler-cpu-running-p", + Fprofiler_cpu_running_p, Sprofiler_cpu_running_p, 0, 0, 0, - doc: /* Return t if sample profiler is running. */) + doc: /* Return non-nil iff cpu profiler is running. */) (void) { - return sample_profiler_running ? Qt : Qnil; + return profiler_cpu_running ? Qt : Qnil; } -DEFUN ("sample-profiler-log", - Fsample_profiler_log, Ssample_profiler_log, +DEFUN ("profiler-cpu-log", Fprofiler_cpu_log, Sprofiler_cpu_log, 0, 0, 0, - doc: /* Return sample profiler log. The data is a list of -(sample nil TIMESTAMP SLOTS), where TIMESTAMP is a timestamp when the -log is collected and SLOTS is a list of slots. */) + doc: /* Return the current cpu profiler log. +The log is a hash-table mapping backtraces to counters which represent +the amount of time spent at those points. Every backtrace is a vector +of functions, where the last few elements may be nil. +Before returning, a new log is allocated for future samples. */) (void) { Lisp_Object result = cpu_log; /* Here we're making the log visible to Elisp , so it's not safe any more for our use afterwards since we can't rely on its special pre-allocated keys anymore. So we have to allocate a new one. */ - cpu_log = (sample_profiler_running - ? make_log (profiler_slot_heap_size, profiler_max_stack_depth) + cpu_log = (profiler_cpu_running + ? make_log (profiler_log_size, profiler_max_stack_depth) : Qnil); Fputhash (Fmake_vector (make_number (1), Qautomatic_gc), make_number (cpu_gc_count), @@ -282,66 +293,74 @@ log is collected and SLOTS is a list of slots. */) cpu_gc_count = 0; return result; } -#endif +#endif /* not defined PROFILER_CPU_SUPPORT */ /* Memory profiler. */ +/* True if memory profiler is running. */ +bool profiler_memory_running; + static Lisp_Object memory_log; -DEFUN ("memory-profiler-start", Fmemory_profiler_start, Smemory_profiler_start, +DEFUN ("profiler-memory-start", Fprofiler_memory_start, Sprofiler_memory_start, 0, 0, 0, - doc: /* Start/restart memory profiler. See also -`profiler-slot-heap-size' and `profiler-max-stack-depth'. */) + doc: /* Start/restart the memory profiler. +The memory profiler will take samples of the call-stack whenever a new +allocation takes place. Note that most small allocations only trigger +the profiler occasionally. +See also `profiler-log-size' and `profiler-max-stack-depth'. */) (void) { - if (memory_profiler_running) + if (profiler_memory_running) error ("Memory profiler is already running"); if (NILP (memory_log)) - memory_log = make_log (profiler_slot_heap_size, + memory_log = make_log (profiler_log_size, profiler_max_stack_depth); - memory_profiler_running = 1; + profiler_memory_running = 1; return Qt; } -DEFUN ("memory-profiler-stop", - Fmemory_profiler_stop, Smemory_profiler_stop, +DEFUN ("profiler-memory-stop", + Fprofiler_memory_stop, Sprofiler_memory_stop, 0, 0, 0, - doc: /* Stop memory profiler. Profiler log will be kept. */) + doc: /* Stop the memory profiler. The profiler log is not affected. */) (void) { - if (!memory_profiler_running) + if (!profiler_memory_running) error ("Memory profiler is not running"); - memory_profiler_running = 0; + profiler_memory_running = 0; return Qt; } -DEFUN ("memory-profiler-running-p", - Fmemory_profiler_running_p, Smemory_profiler_running_p, +DEFUN ("profiler-memory-running-p", + Fprofiler_memory_running_p, Sprofiler_memory_running_p, 0, 0, 0, - doc: /* Return t if memory profiler is running. */) + doc: /* Return non-nil if memory profiler is running. */) (void) { - return memory_profiler_running ? Qt : Qnil; + return profiler_memory_running ? Qt : Qnil; } -DEFUN ("memory-profiler-log", - Fmemory_profiler_log, Smemory_profiler_log, +DEFUN ("profiler-memory-log", + Fprofiler_memory_log, Sprofiler_memory_log, 0, 0, 0, - doc: /* Return memory profiler log. The data is a list of -(memory nil TIMESTAMP SLOTS), where TIMESTAMP is a timestamp when the -log is collected and SLOTS is a list of slots. */) + doc: /* Return the current memory profiler log. +The log is a hash-table mapping backtraces to counters which represent +the amount of memory allocated at those points. Every backtrace is a vector +of functions, where the last few elements may be nil. +Before returning, a new log is allocated for future samples. */) (void) { Lisp_Object result = memory_log; /* Here we're making the log visible to Elisp , so it's not safe any more for our use afterwards since we can't rely on its special pre-allocated keys anymore. So we have to allocate a new one. */ - memory_log = (memory_profiler_running - ? make_log (profiler_slot_heap_size, profiler_max_stack_depth) + memory_log = (profiler_memory_running + ? make_log (profiler_log_size, profiler_max_stack_depth) : Qnil); return result; } @@ -349,24 +368,6 @@ log is collected and SLOTS is a list of slots. */) /* Signals and probes. */ -/* Signal handler for sample profiler. */ - -static void -sigprof_handler (int signal, siginfo_t *info, void *ctx) -{ - eassert (HASH_TABLE_P (cpu_log)); - if (backtrace_list && EQ (*backtrace_list->function, Qautomatic_gc)) - /* Special case the time-count inside GC because the hash-table - code is not prepared to be used while the GC is running. - More specifically it uses ASIZE at many places where it does - not expect the ARRAY_MARK_FLAG to be set. We could try and - harden the hash-table code, but it doesn't seem worth the - effort. */ - cpu_gc_count += current_sample_interval; - else - record_backtrace (XHASH_TABLE (cpu_log), current_sample_interval); -} - /* Record that the current backtrace allocated SIZE bytes. */ void malloc_probe (size_t size) @@ -379,26 +380,26 @@ void syms_of_profiler (void) { DEFVAR_INT ("profiler-max-stack-depth", profiler_max_stack_depth, - doc: /* FIXME */); + doc: /* Number of elements from the call-stack recorded in the log. */); profiler_max_stack_depth = 16; - DEFVAR_INT ("profiler-slot-heap-size", profiler_slot_heap_size, - doc: /* FIXME */); - profiler_slot_heap_size = 10000; + DEFVAR_INT ("profiler-log-size", profiler_log_size, + doc: /* Number of distinct call-stacks that can be recorded in a profiler log. +If the log gets full, some of the least-seen call-stacks will be evicted +to make room for new entries. */); + profiler_log_size = 10000; - /* FIXME: Rename things to start with "profiler-", to use "cpu" instead of - "sample", and to make them sound like they're internal or something. */ #ifdef PROFILER_CPU_SUPPORT cpu_log = Qnil; staticpro (&cpu_log); - defsubr (&Ssample_profiler_start); - defsubr (&Ssample_profiler_stop); - defsubr (&Ssample_profiler_running_p); - defsubr (&Ssample_profiler_log); + defsubr (&Sprofiler_cpu_start); + defsubr (&Sprofiler_cpu_stop); + defsubr (&Sprofiler_cpu_running_p); + defsubr (&Sprofiler_cpu_log); #endif memory_log = Qnil; staticpro (&memory_log); - defsubr (&Smemory_profiler_start); - defsubr (&Smemory_profiler_stop); - defsubr (&Smemory_profiler_running_p); - defsubr (&Smemory_profiler_log); + defsubr (&Sprofiler_memory_start); + defsubr (&Sprofiler_memory_stop); + defsubr (&Sprofiler_memory_running_p); + defsubr (&Sprofiler_memory_log); } |