Changeset 122215 in webkit


Ignore:
Timestamp:
Jul 10, 2012 5:10:47 AM (12 years ago)
Author:
kseo@webkit.org
Message:

Don't destroy the decoded data of an image if WebKit is about to render the image.
https://bugs.webkit.org/show_bug.cgi?id=90721

Patch by Huang Dongsung <luxtella@company100.net> on 2012-07-10
Reviewed by Antti Koivisto.

When the cache capacity of the MemoryCache is exceeded, the decoded data of all
the CachedImages are destroyed. Even the images inside the viewport are
destroyed. However, if the images need to be rendered again due to scoll events
or animation, they must be decoded again. As an extreme case, if there is an
animation with an image when MemoryCache is almost full, the image must be
decoded every frame. This slows down animation and needlessly consumes CPU
cycles.

Therefore, it is better to not destory the decoded data of an image if the image
is inside the viewport because there is high chance that the image needs to be
rendered again soon. This patch reduces the unnecessary repetition of image decoding
on low memory, and also relieves the memory fragmentation because it avoids reallocation
of image frames.

In addition, there is another positive side effect. Currently,
CachedImageClient::willRenderImage() is used only to determine if GIF animation needs
to be paused or not in CachedImage::shouldPauseAnimation(). This patch makes
GIF animation outside the viewort be paused.

This is also a prerequisite for parallel image decoders. Because parallel image
decoders decode an image asynchronously, clients cannot render the image at the time
when the request is made. Clients can draw the image later after receiving image
decoding complete notification. However, there is a problem because MemoryCache can
destroy the decoded data before clients actually render the image. So parallel image decoders
must prevent the decoded data from being destroyed if the image will be rendered
soon.

This patch may consume a little more memory, but furtunately the peak memory usage
is almost the same.

No new tests - no new testable functionality.

  • loader/cache/CachedImage.cpp:

(WebCore::CachedImage::likelyToBeUsedSoon):
(WebCore):
(WebCore::CachedImage::shouldPauseAnimation):

  • loader/cache/CachedImage.h:

(CachedImage):

  • loader/cache/CachedResource.h:

(CachedResource):
(WebCore::CachedResource::likelyToBeUsedSoon):

  • loader/cache/MemoryCache.cpp:

(WebCore::MemoryCache::pruneLiveResourcesToSize):

  • rendering/RenderObject.cpp:

(WebCore::RenderObject::willRenderImage):

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r122212 r122215  
     12012-07-10  Huang Dongsung  <luxtella@company100.net>
     2
     3        Don't destroy the decoded data of an image if WebKit is about to render the image.
     4        https://bugs.webkit.org/show_bug.cgi?id=90721
     5
     6        Reviewed by Antti Koivisto.
     7
     8        When the cache capacity of the MemoryCache is exceeded, the decoded data of all
     9        the CachedImages are destroyed. Even the images inside the viewport are
     10        destroyed.  However, if the images need to be rendered again due to scoll events
     11        or animation, they must be decoded again. As an extreme case, if there is an
     12        animation with an image when MemoryCache is almost full, the image must be
     13        decoded every frame. This slows down animation and needlessly consumes CPU
     14        cycles.
     15
     16        Therefore, it is better to not destory the decoded data of an image if the image
     17        is inside the viewport because there is high chance that the image needs to be
     18        rendered again soon. This patch reduces the unnecessary repetition of image decoding
     19        on low memory, and also relieves the memory fragmentation because it avoids reallocation
     20        of image frames.
     21
     22        In addition, there is another positive side effect. Currently,
     23        CachedImageClient::willRenderImage() is used only to determine if GIF animation needs
     24        to be paused or not in CachedImage::shouldPauseAnimation(). This patch makes
     25        GIF animation outside the viewort be paused.
     26
     27        This is also a prerequisite for parallel image decoders. Because parallel image
     28        decoders decode an image asynchronously, clients cannot render the image at the time
     29        when the request is made. Clients can draw the image later after receiving image
     30        decoding complete notification. However, there is a problem because MemoryCache can
     31        destroy the decoded data before clients actually render the image. So parallel image decoders
     32        must prevent the decoded data from being destroyed if the image will be rendered
     33        soon.
     34
     35        This patch may consume a little more memory, but furtunately the peak memory usage
     36        is almost the same.
     37
     38        No new tests - no new testable functionality.
     39
     40        * loader/cache/CachedImage.cpp:
     41        (WebCore::CachedImage::likelyToBeUsedSoon):
     42        (WebCore):
     43        (WebCore::CachedImage::shouldPauseAnimation):
     44        * loader/cache/CachedImage.h:
     45        (CachedImage):
     46        * loader/cache/CachedResource.h:
     47        (CachedResource):
     48        (WebCore::CachedResource::likelyToBeUsedSoon):
     49        * loader/cache/MemoryCache.cpp:
     50        (WebCore::MemoryCache::pruneLiveResourcesToSize):
     51        * rendering/RenderObject.cpp:
     52        (WebCore::RenderObject::willRenderImage):
     53
    1542012-07-10  Kent Tamura  <tkent@chromium.org>
    255
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r120953 r122215  
    429429}
    430430
     431bool CachedImage::likelyToBeUsedSoon()
     432{
     433    CachedResourceClientWalker<CachedImageClient> walker(m_clients);
     434    while (CachedImageClient* client = walker.next()) {
     435        if (client->willRenderImage(this))
     436            return true;
     437    }
     438
     439    return false;
     440}
     441
    431442void CachedImage::didDraw(const Image* image)
    432443{
     
    446457        return false;
    447458   
    448     CachedResourceClientWalker<CachedImageClient> w(m_clients);
    449     while (CachedImageClient* c = w.next()) {
    450         if (c->willRenderImage(this))
    451             return false;
    452     }
    453 
    454     return true;
     459    return !likelyToBeUsedSoon();
    455460}
    456461
  • trunk/Source/WebCore/loader/cache/CachedImage.h

    r120000 r122215  
    7474    virtual void destroyDecodedData();
    7575
     76    virtual bool likelyToBeUsedSoon();
     77
    7678    virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived);
    7779    virtual void error(CachedResource::Status);
  • trunk/Source/WebCore/loader/cache/CachedResource.h

    r120000 r122215  
    212212    void setOwningCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) { m_owningCachedResourceLoader = cachedResourceLoader; }
    213213   
     214    // MemoryCache does not destroy the decoded data of a CachedResource if the decoded data will be likely used.
     215    virtual bool likelyToBeUsedSoon() { return false; }
     216
    214217    bool isPreloaded() const { return m_preloadCount; }
    215218    void increasePreloadCount() { ++m_preloadCount; }
  • trunk/Source/WebCore/loader/cache/MemoryCache.cpp

    r115454 r122215  
    236236                return;
    237237
     238            // Check to see if the current resource are likely to be used again soon.
     239            if (current->likelyToBeUsedSoon()) {
     240                current = prev;
     241                continue;
     242            }
     243
    238244            // Destroy our decoded data. This will remove us from
    239245            // m_liveDecodedResources, and possibly move us to a different LRU
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r121557 r122215  
    26992699    // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
    27002700    // then we don't want to render either.
    2701     return !document()->inPageCache() && !document()->view()->isOffscreen();
     2701    if (document()->inPageCache() || document()->view()->isOffscreen())
     2702        return false;
     2703
     2704    // If a renderer is outside the viewport, we won't render.
     2705    return viewRect().intersects(absoluteClippedOverflowRect());
    27022706}
    27032707
Note: See TracChangeset for help on using the changeset viewer.