struct profiler_log {
Lisp_Object log;
- EMACS_INT gc_count;
+ EMACS_INT gc_count; /* Samples taken during GC. */
+ EMACS_INT discarded; /* Samples evicted during table overflow. */
};
static struct profiler_log
DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD,
Qnil, false),
- 0 };
+ 0, 0 };
struct Lisp_Hash_Table *h = XHASH_TABLE (log.log);
/* What is special about our hash-tables is that the values are pre-filled
}
}
-static void evict_lower_half (log_t *log)
+static void evict_lower_half (struct profiler_log *plog)
{
+ log_t *log = XHASH_TABLE (plog->log);
ptrdiff_t size = ASIZE (log->key_and_value) / 2;
EMACS_INT median = approximate_median (log, 0, size);
if (XFIXNUM (HASH_VALUE (log, i)) <= median)
{
Lisp_Object key = HASH_KEY (log, i);
+ EMACS_INT count = XFIXNUM (HASH_VALUE (log, i));
+ plog->discarded = saturated_add (plog->discarded, count);
{ /* FIXME: we could make this more efficient. */
Lisp_Object tmp;
XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
size for memory. */
static void
-record_backtrace (log_t *log, EMACS_INT count)
+record_backtrace (struct profiler_log *plog, EMACS_INT count)
{
+ eassert (HASH_TABLE_P (plog->log));
+ log_t *log = XHASH_TABLE (plog->log);
if (log->next_free < 0)
- /* FIXME: transfer the evicted counts to a special entry rather
- than dropping them on the floor. */
- evict_lower_half (log);
+ evict_lower_half (plog);
ptrdiff_t index = log->next_free;
/* Get a "working memory" vector. */
/* Signal handler for sampling profiler. */
static void
-add_sample (struct profiler_log *log, EMACS_INT count)
+add_sample (struct profiler_log *plog, EMACS_INT count)
{
if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
/* Special case the time-count inside GC because the hash-table
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. */
- log->gc_count = saturated_add (log->gc_count, count);
+ plog->gc_count = saturated_add (plog->gc_count, count);
else
- {
- eassert (HASH_TABLE_P (log->log));
- record_backtrace (XHASH_TABLE (log->log), count);
- }
+ record_backtrace (plog, count);
}
export_log (struct profiler_log *log)
{
Lisp_Object result = log->log;
- Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil),
- make_fixnum (log->gc_count),
- result);
+ if (log->gc_count)
+ Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil),
+ make_fixnum (log->gc_count),
+ result);
+ if (log->discarded)
+ Fputhash (CALLN (Fvector, QDiscarded_Samples, Qnil),
+ make_fixnum (log->discarded),
+ result);
/* 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. */
profiler_log_size = 10000;
DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
+ DEFSYM (QDiscarded_Samples, "Discarded Samples");
defsubr (&Sfunction_equal);