Subject: bug#77961: 31.0.50; Rendering HTML email is very slow since commit #eab14d68b2e72b9a6b8b0cc67c9667c2bfbed4f5

From: Gerd Möllmann <[email-masked]>
Date: Tue, 22 Apr 2025 15:28:04 +0200

Eli Zaretskii <[email-masked]> writes:

>> From: Gerd Möllmann <[email-masked]>
>> Cc: [email-masked],  [email-masked],  [email-masked]
>> Date: Tue, 22 Apr 2025 15:04:59 +0200
>> 
>> Eli Zaretskii <[email-masked]> writes:
>> 
>> >> +	      if (dim.width > matrix->matrix_w || new_rows)
>> >> +		{
>> >> +		  row->glyphs[LEFT_MARGIN_AREA]
>> >> +		    = xnrealloc (row->glyphs[LEFT_MARGIN_AREA],
>> >> +				 dim.width, sizeof (struct glyph));
>> >> +		  /* We actually need to clear only the 'frame' member, but
>> >> +		     it's easier to clear everything.  */
>> >> +		  memset (row->glyphs[LEFT_MARGIN_AREA], 0,
>> >> +			  dim.width * sizeof (struct glyph));
>> >> +		}
>> >
>> > This means a very large matrix will not be downsized when possible.
>> > Is that a good idea?  Maybe try replacing '>' with '!=' and see if it
>> > also solves the problem?
>> 
>> It's at least what I originally intended when I wrote that function. On
>> the grounds that if it grew to some size once, it woiuld likely again to
>> that size again. Compare the allocation of the row vector where I did
>> the same, for the same reason.
>> 
>> dispnew.c:
>>   416   /* Enlarge MATRIX->rows if necessary.  New rows are cleared.  */
>>   417   if (matrix->rows_allocated < dim.height)
>>   418     {
>>   419       int old_alloc = matrix->rows_allocated;
>>   420       new_rows = dim.height - matrix->rows_allocated;
>>   421       matrix->rows = xpalloc (matrix->rows, &matrix->rows_allocated,
>>   422                               new_rows, INT_MAX, sizeof *matrix->rows);
>>   423       memset (matrix->rows + old_alloc, 0,
>>   424               (matrix->rows_allocated - old_alloc)
>>   425                 * sizeof *matrix->rows);
>>   426     }
>>   427   else
>>   428     new_rows = 0;
>
> So if the user drags the right side of the frame to make it very wide,
> or just toggles it full-screen, we will grow the glyph matrices and
> never free that space, ever, for as long as the Emacs session lives?
> With today's large screens that could be a significant waste of memory
> that is never returned to the system, I think?
>
> If the problem we want to avoid is reallocating when the size doesn't
> change (which was what happened in this case), then just '!=' should
> prevent it, while simultaneously letting us free some memory when the
> window is down-sized.  Whether such a realloc actually frees memory is
> up to the implementation, but why not let it do what it supposedly
> does best?

It has always been in done in something like the if below. Note the
first two conditions. There have never been re-allocations to shrink a
matrix. 

dispnew.c:
  493       /* If MATRIX->pool is null, MATRIX is responsible for managing
  494          its own memory.  It is a window matrix for window-based redisplay.
  495          Allocate glyph memory from the heap.  */
  496       if (dim.width > matrix->matrix_w
  497           || new_rows
  498           || tab_line_changed_p
  499           || header_line_changed_p
  500           || marginal_areas_changed_p)
  501         {

So shrinking is a new idea. One could try that out, but it's not
something for me ATM, sorry.