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

From: Iñigo Serna <[email-masked]>
Date: Tue, 22 Apr 2025 15:40:32 +0200

I confirm that replacing '>' with '!=' solves the problem as well.

On 22 April 2025 at 15:28 +02, Gerd Möllmann 
<[email-masked]> wrote:

> 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.