aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2019-09-14 00:32:01 -0700
committerPaul Eggert2019-09-14 00:37:26 -0700
commitbac66302e92bdd3a353102d2076548e7e83d92e5 (patch)
tree6007fc144e41b0a0f0eb43bf11100eb4ce8085d4 /src/alloc.c
parente4fb98b542c57fa4856fbeb14230ace34d910117 (diff)
downloademacs-bac66302e92bdd3a353102d2076548e7e83d92e5.tar.gz
emacs-bac66302e92bdd3a353102d2076548e7e83d92e5.zip
Improve gc-cons-percentage calculation
The old calculation relied on a hodgpodge of partly updated GC stats to find a number to multiply gc-cons-percentage by. The new one counts data found by the previous GC, plus half of the data allocated since then; this is more systematic albeit still ad hoc. * src/alloc.c (consing_until_gc, gc_threshold, consing_threshold): Now EMACS_INT, not intmax_t. (HI_THRESHOLD): New macro. (tally_consing): New function. (make_interval, allocate_string, allocate_string_data) (make_float, free_cons, allocate_vectorlike, Fmake_symbol): Use it. (allow_garbage_collection, inhibit_garbage_collection) (consing_threshold, garbage_collect): Use HI_THRESHOLD rather than INTMAX_MAX. (consing_threshold): New arg SINCE_GC. All callers changed. (bump_consing_until_gc): Return new consing_until_gc, instead of nil. All callers changed. Don’t worry about overflow since we now saturate at HI_THRESHOLD. Guess that half of recently-allocated objects are still alive, instead of relying on the previous (even less-accurate) hodgepodge. (maybe_garbage_collect): New function. (garbage_collect): Work even if a finalizer disables or enables memory profiling. Do not use malloc_probe if GC reclaimed nothing. * src/lisp.h (maybe_gc): Call maybe_garbage_collect instead of garbage_collect.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c127
1 files changed, 74 insertions, 53 deletions
diff --git a/src/alloc.c b/src/alloc.c
index ca8311cc00a..497f600551e 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -224,7 +224,7 @@ struct emacs_globals globals;
224 224
225/* maybe_gc collects garbage if this goes negative. */ 225/* maybe_gc collects garbage if this goes negative. */
226 226
227intmax_t consing_until_gc; 227EMACS_INT consing_until_gc;
228 228
229#ifdef HAVE_PDUMPER 229#ifdef HAVE_PDUMPER
230/* Number of finalizers run: used to loop over GC until we stop 230/* Number of finalizers run: used to loop over GC until we stop
@@ -238,9 +238,16 @@ bool gc_in_progress;
238 238
239/* System byte and object counts reported by GC. */ 239/* System byte and object counts reported by GC. */
240 240
241/* Assume byte counts fit in uintptr_t and object counts fit into
242 intptr_t. */
241typedef uintptr_t byte_ct; 243typedef uintptr_t byte_ct;
242typedef intptr_t object_ct; 244typedef intptr_t object_ct;
243 245
246/* Large-magnitude value for a threshold count, which fits in EMACS_INT.
247 Using only half the EMACS_INT range avoids overflow hassles.
248 There is no need to fit these counts into fixnums. */
249#define HI_THRESHOLD (EMACS_INT_MAX / 2)
250
244/* Number of live and free conses etc. counted by the most-recent GC. */ 251/* Number of live and free conses etc. counted by the most-recent GC. */
245 252
246static struct gcstat 253static struct gcstat
@@ -299,7 +306,7 @@ static intptr_t garbage_collection_inhibited;
299 306
300/* The GC threshold in bytes, the last time it was calculated 307/* The GC threshold in bytes, the last time it was calculated
301 from gc-cons-threshold and gc-cons-percentage. */ 308 from gc-cons-threshold and gc-cons-percentage. */
302static intmax_t gc_threshold; 309static EMACS_INT gc_threshold;
303 310
304/* If nonzero, this is a warning delivered by malloc and not yet 311/* If nonzero, this is a warning delivered by malloc and not yet
305 displayed. */ 312 displayed. */
@@ -536,6 +543,15 @@ XFLOAT_INIT (Lisp_Object f, double n)
536 XFLOAT (f)->u.data = n; 543 XFLOAT (f)->u.data = n;
537} 544}
538 545
546/* Account for allocation of NBYTES in the heap. This is a separate
547 function to avoid hassles with implementation-defined conversion
548 from unsigned to signed types. */
549static void
550tally_consing (ptrdiff_t nbytes)
551{
552 consing_until_gc -= nbytes;
553}
554
539#ifdef DOUG_LEA_MALLOC 555#ifdef DOUG_LEA_MALLOC
540static bool 556static bool
541pointers_fit_in_lispobj_p (void) 557pointers_fit_in_lispobj_p (void)
@@ -1372,7 +1388,7 @@ make_interval (void)
1372 1388
1373 MALLOC_UNBLOCK_INPUT; 1389 MALLOC_UNBLOCK_INPUT;
1374 1390
1375 consing_until_gc -= sizeof (struct interval); 1391 tally_consing (sizeof (struct interval));
1376 intervals_consed++; 1392 intervals_consed++;
1377 RESET_INTERVAL (val); 1393 RESET_INTERVAL (val);
1378 val->gcmarkbit = 0; 1394 val->gcmarkbit = 0;
@@ -1739,7 +1755,7 @@ allocate_string (void)
1739 MALLOC_UNBLOCK_INPUT; 1755 MALLOC_UNBLOCK_INPUT;
1740 1756
1741 ++strings_consed; 1757 ++strings_consed;
1742 consing_until_gc -= sizeof *s; 1758 tally_consing (sizeof *s);
1743 1759
1744#ifdef GC_CHECK_STRING_BYTES 1760#ifdef GC_CHECK_STRING_BYTES
1745 if (!noninteractive) 1761 if (!noninteractive)
@@ -1859,7 +1875,7 @@ allocate_string_data (struct Lisp_String *s,
1859 old_data->string = NULL; 1875 old_data->string = NULL;
1860 } 1876 }
1861 1877
1862 consing_until_gc -= needed; 1878 tally_consing (needed);
1863} 1879}
1864 1880
1865 1881
@@ -2464,7 +2480,7 @@ make_float (double float_value)
2464 2480
2465 XFLOAT_INIT (val, float_value); 2481 XFLOAT_INIT (val, float_value);
2466 eassert (!XFLOAT_MARKED_P (XFLOAT (val))); 2482 eassert (!XFLOAT_MARKED_P (XFLOAT (val)));
2467 consing_until_gc -= sizeof (struct Lisp_Float); 2483 tally_consing (sizeof (struct Lisp_Float));
2468 floats_consed++; 2484 floats_consed++;
2469 return val; 2485 return val;
2470} 2486}
@@ -2535,8 +2551,8 @@ free_cons (struct Lisp_Cons *ptr)
2535 ptr->u.s.u.chain = cons_free_list; 2551 ptr->u.s.u.chain = cons_free_list;
2536 ptr->u.s.car = dead_object (); 2552 ptr->u.s.car = dead_object ();
2537 cons_free_list = ptr; 2553 cons_free_list = ptr;
2538 if (INT_ADD_WRAPV (consing_until_gc, sizeof *ptr, &consing_until_gc)) 2554 ptrdiff_t nbytes = sizeof *ptr;
2539 consing_until_gc = INTMAX_MAX; 2555 tally_consing (-nbytes);
2540} 2556}
2541 2557
2542DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2558DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -3153,7 +3169,7 @@ allocate_vectorlike (ptrdiff_t len)
3153 if (find_suspicious_object_in_range (p, (char *) p + nbytes)) 3169 if (find_suspicious_object_in_range (p, (char *) p + nbytes))
3154 emacs_abort (); 3170 emacs_abort ();
3155 3171
3156 consing_until_gc -= nbytes; 3172 tally_consing (nbytes);
3157 vector_cells_consed += len; 3173 vector_cells_consed += len;
3158 3174
3159 MALLOC_UNBLOCK_INPUT; 3175 MALLOC_UNBLOCK_INPUT;
@@ -3438,7 +3454,7 @@ Its value is void, and its function definition and property list are nil. */)
3438 MALLOC_UNBLOCK_INPUT; 3454 MALLOC_UNBLOCK_INPUT;
3439 3455
3440 init_symbol (val, name); 3456 init_symbol (val, name);
3441 consing_until_gc -= sizeof (struct Lisp_Symbol); 3457 tally_consing (sizeof (struct Lisp_Symbol));
3442 symbols_consed++; 3458 symbols_consed++;
3443 return val; 3459 return val;
3444} 3460}
@@ -5477,7 +5493,7 @@ staticpro (Lisp_Object const *varaddress)
5477static void 5493static void
5478allow_garbage_collection (intmax_t consing) 5494allow_garbage_collection (intmax_t consing)
5479{ 5495{
5480 consing_until_gc = consing - (INTMAX_MAX - consing_until_gc); 5496 consing_until_gc = consing - (HI_THRESHOLD - consing_until_gc);
5481 garbage_collection_inhibited--; 5497 garbage_collection_inhibited--;
5482} 5498}
5483 5499
@@ -5487,7 +5503,7 @@ inhibit_garbage_collection (void)
5487 ptrdiff_t count = SPECPDL_INDEX (); 5503 ptrdiff_t count = SPECPDL_INDEX ();
5488 record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc); 5504 record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc);
5489 garbage_collection_inhibited++; 5505 garbage_collection_inhibited++;
5490 consing_until_gc = INTMAX_MAX; 5506 consing_until_gc = HI_THRESHOLD;
5491 return count; 5507 return count;
5492} 5508}
5493 5509
@@ -5761,11 +5777,13 @@ mark_and_sweep_weak_table_contents (void)
5761 } 5777 }
5762} 5778}
5763 5779
5764/* Return the number of bytes to cons between GCs, assuming 5780/* Return the number of bytes to cons between GCs, given THRESHOLD and
5765 gc-cons-threshold is THRESHOLD and gc-cons-percentage is 5781 PERCENTAGE. When calculating a threshold based on PERCENTAGE,
5766 PERCENTAGE. */ 5782 assume SINCE_GC bytes have been allocated since the most recent GC.
5767static intmax_t 5783 The returned value is positive and no greater than HI_THRESHOLD. */
5768consing_threshold (intmax_t threshold, Lisp_Object percentage) 5784static EMACS_INT
5785consing_threshold (intmax_t threshold, Lisp_Object percentage,
5786 intmax_t since_gc)
5769{ 5787{
5770 if (!NILP (Vmemory_full)) 5788 if (!NILP (Vmemory_full))
5771 return memory_full_cons_threshold; 5789 return memory_full_cons_threshold;
@@ -5775,42 +5793,33 @@ consing_threshold (intmax_t threshold, Lisp_Object percentage)
5775 if (FLOATP (percentage)) 5793 if (FLOATP (percentage))
5776 { 5794 {
5777 double tot = (XFLOAT_DATA (percentage) 5795 double tot = (XFLOAT_DATA (percentage)
5778 * total_bytes_of_live_objects ()); 5796 * (total_bytes_of_live_objects () + since_gc));
5779 if (threshold < tot) 5797 if (threshold < tot)
5780 { 5798 {
5781 if (tot < INTMAX_MAX) 5799 if (tot < HI_THRESHOLD)
5782 threshold = tot; 5800 return tot;
5783 else 5801 else
5784 threshold = INTMAX_MAX; 5802 return HI_THRESHOLD;
5785 } 5803 }
5786 } 5804 }
5787 return threshold; 5805 return min (threshold, HI_THRESHOLD);
5788 } 5806 }
5789} 5807}
5790 5808
5791/* Adjust consing_until_gc, assuming gc-cons-threshold is THRESHOLD and 5809/* Adjust consing_until_gc and gc_threshold, given THRESHOLD and PERCENTAGE.
5792 gc-cons-percentage is PERCENTAGE. */ 5810 Return the updated consing_until_gc. */
5793static Lisp_Object 5811
5812static EMACS_INT
5794bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage) 5813bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage)
5795{ 5814{
5796 /* If consing_until_gc is negative leave it alone, since this prevents 5815 /* Guesstimate that half the bytes allocated since the most
5797 negative integer overflow and a GC would have been done soon anyway. */ 5816 recent GC are still in use. */
5798 if (0 <= consing_until_gc) 5817 EMACS_INT since_gc = (gc_threshold - consing_until_gc) >> 1;
5799 { 5818 EMACS_INT new_gc_threshold = consing_threshold (threshold, percentage,
5800 threshold = consing_threshold (threshold, percentage); 5819 since_gc);
5801 intmax_t sum; 5820 consing_until_gc += new_gc_threshold - gc_threshold;
5802 if (INT_ADD_WRAPV (consing_until_gc, threshold - gc_threshold, &sum)) 5821 gc_threshold = new_gc_threshold;
5803 { 5822 return consing_until_gc;
5804 /* Scale the threshold down so that consing_until_gc does
5805 not overflow. */
5806 sum = INTMAX_MAX;
5807 threshold = INTMAX_MAX - consing_until_gc + gc_threshold;
5808 }
5809 consing_until_gc = sum;
5810 gc_threshold = threshold;
5811 }
5812
5813 return Qnil;
5814} 5823}
5815 5824
5816/* Watch changes to gc-cons-threshold. */ 5825/* Watch changes to gc-cons-threshold. */
@@ -5821,7 +5830,8 @@ watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval,
5821 intmax_t threshold; 5830 intmax_t threshold;
5822 if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold))) 5831 if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold)))
5823 return Qnil; 5832 return Qnil;
5824 return bump_consing_until_gc (threshold, Vgc_cons_percentage); 5833 bump_consing_until_gc (threshold, Vgc_cons_percentage);
5834 return Qnil;
5825} 5835}
5826 5836
5827/* Watch changes to gc-cons-percentage. */ 5837/* Watch changes to gc-cons-percentage. */
@@ -5829,7 +5839,18 @@ static Lisp_Object
5829watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, 5839watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval,
5830 Lisp_Object operation, Lisp_Object where) 5840 Lisp_Object operation, Lisp_Object where)
5831{ 5841{
5832 return bump_consing_until_gc (gc_cons_threshold, newval); 5842 bump_consing_until_gc (gc_cons_threshold, newval);
5843 return Qnil;
5844}
5845
5846/* It may be time to collect garbage. Recalculate consing_until_gc,
5847 since it might depend on current usage, and do the garbage
5848 collection if the recalculation says so. */
5849void
5850maybe_garbage_collect (void)
5851{
5852 if (bump_consing_until_gc (gc_cons_threshold, Vgc_cons_percentage) < 0)
5853 garbage_collect ();
5833} 5854}
5834 5855
5835/* Subroutine of Fgarbage_collect that does most of the work. */ 5856/* Subroutine of Fgarbage_collect that does most of the work. */
@@ -5841,7 +5862,6 @@ garbage_collect (void)
5841 bool message_p; 5862 bool message_p;
5842 ptrdiff_t count = SPECPDL_INDEX (); 5863 ptrdiff_t count = SPECPDL_INDEX ();
5843 struct timespec start; 5864 struct timespec start;
5844 byte_ct tot_before = 0;
5845 5865
5846 eassert (weak_hash_tables == NULL); 5866 eassert (weak_hash_tables == NULL);
5847 5867
@@ -5856,14 +5876,15 @@ garbage_collect (void)
5856 FOR_EACH_BUFFER (nextb) 5876 FOR_EACH_BUFFER (nextb)
5857 compact_buffer (nextb); 5877 compact_buffer (nextb);
5858 5878
5859 if (profiler_memory_running) 5879 byte_ct tot_before = (profiler_memory_running
5860 tot_before = total_bytes_of_live_objects (); 5880 ? total_bytes_of_live_objects ()
5881 : (byte_ct) -1);
5861 5882
5862 start = current_timespec (); 5883 start = current_timespec ();
5863 5884
5864 /* In case user calls debug_print during GC, 5885 /* In case user calls debug_print during GC,
5865 don't let that cause a recursive GC. */ 5886 don't let that cause a recursive GC. */
5866 consing_until_gc = INTMAX_MAX; 5887 consing_until_gc = HI_THRESHOLD;
5867 5888
5868 /* Save what's currently displayed in the echo area. Don't do that 5889 /* Save what's currently displayed in the echo area. Don't do that
5869 if we are GC'ing because we've run out of memory, since 5890 if we are GC'ing because we've run out of memory, since
@@ -5975,7 +5996,7 @@ garbage_collect (void)
5975 unblock_input (); 5996 unblock_input ();
5976 5997
5977 consing_until_gc = gc_threshold 5998 consing_until_gc = gc_threshold
5978 = consing_threshold (gc_cons_threshold, Vgc_cons_percentage); 5999 = consing_threshold (gc_cons_threshold, Vgc_cons_percentage, 0);
5979 6000
5980 if (garbage_collection_messages && NILP (Vmemory_full)) 6001 if (garbage_collection_messages && NILP (Vmemory_full))
5981 { 6002 {
@@ -6008,11 +6029,11 @@ garbage_collect (void)
6008 gcs_done++; 6029 gcs_done++;
6009 6030
6010 /* Collect profiling data. */ 6031 /* Collect profiling data. */
6011 if (profiler_memory_running) 6032 if (tot_before != (byte_ct) -1)
6012 { 6033 {
6013 byte_ct tot_after = total_bytes_of_live_objects (); 6034 byte_ct tot_after = total_bytes_of_live_objects ();
6014 byte_ct swept = tot_before <= tot_after ? 0 : tot_before - tot_after; 6035 if (tot_after < tot_before)
6015 malloc_probe (min (swept, SIZE_MAX)); 6036 malloc_probe (min (tot_before - tot_after, SIZE_MAX));
6016 } 6037 }
6017} 6038}
6018 6039