summaryrefslogtreecommitdiff
path: root/src/profiler.c
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2012-09-24 22:30:46 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2012-09-24 22:30:46 -0400
commit6521894d1aa5a1017dd6f3f55b5e7c11dde5d004 (patch)
treef74f3953cb1ff8905eb9e7b3e3cc39bae8edd18c /src/profiler.c
parentad942b63d7a9b984752f46bc2049fe10e488230d (diff)
downloademacs-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.c177
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);
}