aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2023-03-10 15:54:10 -0500
committerStefan Monnier2023-03-10 15:54:10 -0500
commitd236ab09300070696f21ebfda49678b11c2327eb (patch)
treeb49f1f03f7f9168695209668f0560868e6d76672 /src
parent83be04c66ffaec86aee136b9a94979169d1ba68d (diff)
downloademacs-d236ab09300070696f21ebfda49678b11c2327eb.tar.gz
emacs-d236ab09300070696f21ebfda49678b11c2327eb.zip
src/profiler.c: Keep track of the discarded counts
When the table overflows and wh evict entries, keep track of those counts in a global counter so we can see the proportion of samples this represents. * src/profiler.c (struct profiler_log): Add `discarded` field. (evict_lower_half): Change arg to be `struct profiler_log`. Transfer counts to the new `discarded` field. (record_backtrace): Change arg to be `struct profiler_log`. (add_sample): Adjust call accordingly. (export_log): Add `discarded` counts to the result. Onle add the GC and `discarded` counts if they're non-zero. (syms_of_profiler): Define new symbol `Discarded Samples`.
Diffstat (limited to 'src')
-rw-r--r--src/profiler.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/src/profiler.c b/src/profiler.c
index d5a5a2cf5f3..6217071ef9c 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -51,7 +51,8 @@ static const struct hash_table_test hashtest_profiler =
51 51
52struct profiler_log { 52struct profiler_log {
53 Lisp_Object log; 53 Lisp_Object log;
54 EMACS_INT gc_count; 54 EMACS_INT gc_count; /* Samples taken during GC. */
55 EMACS_INT discarded; /* Samples evicted during table overflow. */
55}; 56};
56 57
57static struct profiler_log 58static struct profiler_log
@@ -70,7 +71,7 @@ make_log (void)
70 DEFAULT_REHASH_SIZE, 71 DEFAULT_REHASH_SIZE,
71 DEFAULT_REHASH_THRESHOLD, 72 DEFAULT_REHASH_THRESHOLD,
72 Qnil, false), 73 Qnil, false),
73 0 }; 74 0, 0 };
74 struct Lisp_Hash_Table *h = XHASH_TABLE (log.log); 75 struct Lisp_Hash_Table *h = XHASH_TABLE (log.log);
75 76
76 /* What is special about our hash-tables is that the values are pre-filled 77 /* What is special about our hash-tables is that the values are pre-filled
@@ -123,8 +124,9 @@ static EMACS_INT approximate_median (log_t *log,
123 } 124 }
124} 125}
125 126
126static void evict_lower_half (log_t *log) 127static void evict_lower_half (struct profiler_log *plog)
127{ 128{
129 log_t *log = XHASH_TABLE (plog->log);
128 ptrdiff_t size = ASIZE (log->key_and_value) / 2; 130 ptrdiff_t size = ASIZE (log->key_and_value) / 2;
129 EMACS_INT median = approximate_median (log, 0, size); 131 EMACS_INT median = approximate_median (log, 0, size);
130 132
@@ -134,6 +136,8 @@ static void evict_lower_half (log_t *log)
134 if (XFIXNUM (HASH_VALUE (log, i)) <= median) 136 if (XFIXNUM (HASH_VALUE (log, i)) <= median)
135 { 137 {
136 Lisp_Object key = HASH_KEY (log, i); 138 Lisp_Object key = HASH_KEY (log, i);
139 EMACS_INT count = XFIXNUM (HASH_VALUE (log, i));
140 plog->discarded = saturated_add (plog->discarded, count);
137 { /* FIXME: we could make this more efficient. */ 141 { /* FIXME: we could make this more efficient. */
138 Lisp_Object tmp; 142 Lisp_Object tmp;
139 XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ 143 XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
@@ -155,12 +159,12 @@ static void evict_lower_half (log_t *log)
155 size for memory. */ 159 size for memory. */
156 160
157static void 161static void
158record_backtrace (log_t *log, EMACS_INT count) 162record_backtrace (struct profiler_log *plog, EMACS_INT count)
159{ 163{
164 eassert (HASH_TABLE_P (plog->log));
165 log_t *log = XHASH_TABLE (plog->log);
160 if (log->next_free < 0) 166 if (log->next_free < 0)
161 /* FIXME: transfer the evicted counts to a special entry rather 167 evict_lower_half (plog);
162 than dropping them on the floor. */
163 evict_lower_half (log);
164 ptrdiff_t index = log->next_free; 168 ptrdiff_t index = log->next_free;
165 169
166 /* Get a "working memory" vector. */ 170 /* Get a "working memory" vector. */
@@ -240,7 +244,7 @@ static EMACS_INT current_sampling_interval;
240/* Signal handler for sampling profiler. */ 244/* Signal handler for sampling profiler. */
241 245
242static void 246static void
243add_sample (struct profiler_log *log, EMACS_INT count) 247add_sample (struct profiler_log *plog, EMACS_INT count)
244{ 248{
245 if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */ 249 if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
246 /* Special case the time-count inside GC because the hash-table 250 /* Special case the time-count inside GC because the hash-table
@@ -249,12 +253,9 @@ add_sample (struct profiler_log *log, EMACS_INT count)
249 not expect the ARRAY_MARK_FLAG to be set. We could try and 253 not expect the ARRAY_MARK_FLAG to be set. We could try and
250 harden the hash-table code, but it doesn't seem worth the 254 harden the hash-table code, but it doesn't seem worth the
251 effort. */ 255 effort. */
252 log->gc_count = saturated_add (log->gc_count, count); 256 plog->gc_count = saturated_add (plog->gc_count, count);
253 else 257 else
254 { 258 record_backtrace (plog, count);
255 eassert (HASH_TABLE_P (log->log));
256 record_backtrace (XHASH_TABLE (log->log), count);
257 }
258} 259}
259 260
260 261
@@ -424,9 +425,14 @@ static Lisp_Object
424export_log (struct profiler_log *log) 425export_log (struct profiler_log *log)
425{ 426{
426 Lisp_Object result = log->log; 427 Lisp_Object result = log->log;
427 Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil), 428 if (log->gc_count)
428 make_fixnum (log->gc_count), 429 Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil),
429 result); 430 make_fixnum (log->gc_count),
431 result);
432 if (log->discarded)
433 Fputhash (CALLN (Fvector, QDiscarded_Samples, Qnil),
434 make_fixnum (log->discarded),
435 result);
430 /* Here we're making the log visible to Elisp, so it's not safe any 436 /* Here we're making the log visible to Elisp, so it's not safe any
431 more for our use afterwards since we can't rely on its special 437 more for our use afterwards since we can't rely on its special
432 pre-allocated keys anymore. So we have to allocate a new one. */ 438 pre-allocated keys anymore. So we have to allocate a new one. */
@@ -595,6 +601,7 @@ to make room for new entries. */);
595 profiler_log_size = 10000; 601 profiler_log_size = 10000;
596 602
597 DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal"); 603 DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
604 DEFSYM (QDiscarded_Samples, "Discarded Samples");
598 605
599 defsubr (&Sfunction_equal); 606 defsubr (&Sfunction_equal);
600 607