<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>263521</bug_id>
          
          <creation_ts>2023-10-23 06:26:18 -0700</creation_ts>
          <short_desc>Memory consumption/leak with img out of viewport and lazy loading</short_desc>
          <delta_ts>2023-11-14 19:58:17 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>New Bugs</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=262238</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Przemyslaw Gorszkowski">pgorszkowski</reporter>
          <assigned_to name="Przemyslaw Gorszkowski">pgorszkowski</assigned_to>
          <cc>jblas</cc>
    
    <cc>webkit-bug-importer</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1986798</commentid>
    <comment_count>0</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-23 06:26:18 -0700</bug_when>
    <thetext>Originally the problem was reported for WPE 2.38: https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1194

The same problem can be also reproduced on current WebKitGTK.

I create a simple test case on which the problem can be observed: https://people.igalia.com/pgorszkowski/img_lazy_loading.html?useLazy=1

The idea of the simple test case is:
1. create 1000 images with lazy loading(the same src) below the visible viewport
2. after 100ms remove existing images, and create another 1000 new images with lazy loading (the same src) below the visible viewport
3. do this recreation 1000 times

With lazy loading the memory grows quite fast from ~200MB to 2000MB after ~500 iterations

Without lazy loading (https://people.igalia.com/pgorszkowski/img_lazy_loading.html?useLazy=0) the memory stays on stable level ~200MB (never grows above 250MB) and after 1000 iterations it is still ~200MB</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1986799</commentid>
    <comment_count>1</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-23 06:43:51 -0700</bug_when>
    <thetext>I found that this fix solves the problem:

diff --git a/Source/WebCore/html/HTMLImageElement.cpp b/Source/WebCore/html/HTMLImageElement.cpp
index 3e4855fd20e2..5ddc923b1568 100644
--- a/Source/WebCore/html/HTMLImageElement.cpp
+++ b/Source/WebCore/html/HTMLImageElement.cpp
@@ -514,6 +518,8 @@ void HTMLImageElement::removedFromAncestor(RemovalType removalType, ContainerNod
         selectImageSource(RelevantMutation::Yes);
     }
 
+    m_imageLoader-&gt;clearImage();
+
     HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
     FormAssociatedElement::elementRemovedFromAncestor(*this, removalType);
 }

but I am not sure about possible regressions or other impact which it can have (so I would be glad for any comments or advices).

I will elaborate more about my analysis in the next comment, which will be probably quite long because it is rather a complex process.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1986821</commentid>
    <comment_count>2</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2023-10-23 08:59:46 -0700</bug_when>
    <thetext>Is this the same as bug 262238?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1986899</commentid>
    <comment_count>3</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-23 12:27:16 -0700</bug_when>
    <thetext>Yes, it is. 

I have checked also my proposal fix and it solves the problem from https://bugs.webkit.org/show_bug.cgi?id=262238</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1986901</commentid>
    <comment_count>4</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-23 12:28:54 -0700</bug_when>
    <thetext>But I checked it on WebKitGTK. It would be better to confirm it also on Safari.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1987382</commentid>
    <comment_count>5</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-25 06:41:18 -0700</bug_when>
    <thetext>So the main problem is when the img element contains loading=&quot;lazy&quot; and the element is outside the viewport which causes deferring the loading of the image until it is in visible area. The deferring load also increases the img element reference by m_protectedElement member in ImageLoader (which is kept by HTMLImageElement).
m_protectedElement is reset (and additional reference of the image element is decreased) when image is finally loaded.

The problem with dangling HTMLImageElement is when we remove it from the document before the image resource is finally loaded. When we remove the HTMLImageElement from document but image loading is deferred, the imageLoader still keeps additional reference for HTMLImageElement in m_protectedElement which causes the GC will never remove it (loading will never be done because HTMLImageElement is removed from document and will never be considered as in visible area).

To solve the problem we can add m_imageLoader-&gt;clearImage(); in HTMLImageElement::removedFromAncestor if the loading image was deferred.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1987506</commentid>
    <comment_count>6</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-25 12:51:48 -0700</bug_when>
    <thetext>Pull request: https://github.com/WebKit/WebKit/pull/19559</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1987509</commentid>
    <comment_count>7</comment_count>
    <who name="Przemyslaw Gorszkowski">pgorszkowski</who>
    <bug_when>2023-10-25 13:02:25 -0700</bug_when>
    <thetext>*** Bug 262238 has been marked as a duplicate of this bug. ***</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1988473</commentid>
    <comment_count>8</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2023-10-30 06:27:14 -0700</bug_when>
    <thetext>&lt;rdar://problem/117683012&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1992654</commentid>
    <comment_count>9</comment_count>
    <who name="EWS">ews-feeder</who>
    <bug_when>2023-11-14 19:58:16 -0800</bug_when>
    <thetext>Committed 270745@main (78e4577732ca): &lt;https://commits.webkit.org/270745@main&gt;

Reviewed commits have been landed. Closing PR #19559 and removing active labels.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>