Skip to content
Permalink
Browse files
Throw away StyleResolvers that haven't been used for a long time.
<http://webkit.org/b/104314>

Reviewed by Antti Koivisto.

A lot of memory gets tied up in StyleResolver and the structures and caches that hang from it.
Add a mechanism to throw it away after it's been unused for a while (1 minute.)
This frees up large amounts of memory on inactive pages (background tabs) and static content.

We already have a number of scenarios where the document style is invalidated by throwing away
the StyleResolver so the major code paths are prepared for having a null StyleResolver* on occasion.

~20MB progression on Membuster3.

* css/StyleResolver.cpp:
(WebCore::StyleResolver::styleForElement):
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::pseudoStyleForElement):
(WebCore::StyleResolver::styleForPage):

    Call document()->didAccessStyleResolver() from the relevant parts of StyleResolver's public API.
    This prevents Document from throwing the StyleResolver away for 1 minute after it's used.

* dom/Document.h:
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::createStyleResolver):
(WebCore::Document::didAccessStyleResolver):
(WebCore::Document::styleResolverThrowawayTimerFired):

    Add a mechanism to call clearStyleResolver() on a refreshing timer.

* dom/Element.cpp:
(WebCore::Element::attributeChanged):

    If an attribute change occurs while the document doesn't have a StyleResolver, dirty the element style
    since we can't be sure that the attribute change didn't affect any rules.


Canonical link: https://commits.webkit.org/122531@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@136956 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Andreas Kling committed Dec 7, 2012
1 parent 872a162 commit bf91079d9506455803ff1621b024e620e21e3800
Showing with 77 additions and 0 deletions.
  1. +40 −0 Source/WebCore/ChangeLog
  2. +8 −0 Source/WebCore/css/StyleResolver.cpp
  3. +20 −0 Source/WebCore/dom/Document.cpp
  4. +6 −0 Source/WebCore/dom/Document.h
  5. +3 −0 Source/WebCore/dom/Element.cpp
@@ -1,3 +1,43 @@
2012-12-07 Andreas Kling <akling@apple.com>

Throw away StyleResolvers that haven't been used for a long time.
<http://webkit.org/b/104314>

Reviewed by Antti Koivisto.

A lot of memory gets tied up in StyleResolver and the structures and caches that hang from it.
Add a mechanism to throw it away after it's been unused for a while (1 minute.)
This frees up large amounts of memory on inactive pages (background tabs) and static content.

We already have a number of scenarios where the document style is invalidated by throwing away
the StyleResolver so the major code paths are prepared for having a null StyleResolver* on occasion.

~20MB progression on Membuster3.

* css/StyleResolver.cpp:
(WebCore::StyleResolver::styleForElement):
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::pseudoStyleForElement):
(WebCore::StyleResolver::styleForPage):

Call document()->didAccessStyleResolver() from the relevant parts of StyleResolver's public API.
This prevents Document from throwing the StyleResolver away for 1 minute after it's used.

* dom/Document.h:
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::createStyleResolver):
(WebCore::Document::didAccessStyleResolver):
(WebCore::Document::styleResolverThrowawayTimerFired):

Add a mechanism to call clearStyleResolver() on a refreshing timer.

* dom/Element.cpp:
(WebCore::Element::attributeChanged):

If an attribute change occurs while the document doesn't have a StyleResolver, dirty the element style
since we can't be sure that the attribute change didn't affect any rules.

2012-12-07 Antonio Gomes <a1.gomes@sisa.samsung.com>

REGRESSION(r136947): Made two tests fail on all platforms (Requested by tonikitoo-ll on #webkit).
@@ -1601,6 +1601,8 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS
if (cloneForParent)
m_parentStyle = 0;

document()->didAccessStyleResolver();

// Now return the style.
return m_style.release();
}
@@ -1654,6 +1656,8 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* eleme
}
}

document()->didAccessStyleResolver();

return m_style.release();
}

@@ -1757,6 +1761,8 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(PseudoId pseudo, El
// Start loading resources referenced by this style.
loadPendingResources();

document()->didAccessStyleResolver();

// Now return the style.
return m_style.release();
}
@@ -1796,6 +1802,8 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
// Start loading resources referenced by this style.
loadPendingResources();

document()->didAccessStyleResolver();

// Now return the style.
return m_style.release();
}
@@ -437,6 +437,8 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
: ContainerNode(0, CreateDocument)
, TreeScope(this)
, m_guardRefCount(0)
, m_styleResolverThrowawayTimer(this, &Document::styleResolverThrowawayTimerFired)
, m_lastStyleResolverAccessTime(0)
, m_contextFeatures(ContextFeatures::defaultSwitch())
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
@@ -4433,6 +4435,24 @@ void Document::sharedObjectPoolClearTimerFired(Timer<Document>*)
m_sharedObjectPool.clear();
}

void Document::didAccessStyleResolver()
{
static const int timeBeforeThrowingAwayStyleResolverAfterLastUseInSeconds = 60;
static const int holdOffTimeBeforeReschedulingTimerInSeconds = 5;

double currentTime = WTF::currentTime();

if (currentTime > m_lastStyleResolverAccessTime + holdOffTimeBeforeReschedulingTimerInSeconds) {
m_styleResolverThrowawayTimer.startOneShot(timeBeforeThrowingAwayStyleResolverAfterLastUseInSeconds);
m_lastStyleResolverAccessTime = currentTime;
}
}

void Document::styleResolverThrowawayTimerFired(Timer<Document>*)
{
clearStyleResolver();
}

PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
XPathNSResolver* resolver,
ExceptionCode& ec)
@@ -496,6 +496,8 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC
*/
void styleResolverChanged(StyleResolverUpdateFlag);

void didAccessStyleResolver();

void evaluateMediaQueryList();

// Never returns 0.
@@ -1260,6 +1262,10 @@ class Document : public ContainerNode, public TreeScope, public ScriptExecutionC

int m_guardRefCount;

void styleResolverThrowawayTimerFired(Timer<Document>*);
Timer<Document> m_styleResolverThrowawayTimer;
double m_lastStyleResolverAccessTime;

OwnPtr<StyleResolver> m_styleResolver;
bool m_didCalculateStyleResolver;
bool m_hasDirtyStyleResolver;
@@ -799,6 +799,9 @@ void Element::attributeChanged(const QualifiedName& name, const AtomicString& ne

invalidateNodeListCachesInAncestors(&name, this);

// If there is currently no StyleResolver, we can't be sure that this attribute change won't affect style.
shouldInvalidateStyle |= !styleResolver;

if (shouldInvalidateStyle)
setNeedsStyleRecalc();

0 comments on commit bf91079

Please sign in to comment.