Bug 147050 - [Content Extensions] Cache actions with domains that match everything
Summary: [Content Extensions] Cache actions with domains that match everything
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Alex Christensen
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-07-17 14:32 PDT by Alex Christensen
Modified: 2015-07-20 19:29 PDT (History)
5 users (show)

See Also:


Attachments
Patch (33.30 KB, patch)
2015-07-17 14:39 PDT, Alex Christensen
no flags Details | Formatted Diff | Diff
Patch (33.47 KB, patch)
2015-07-17 15:14 PDT, Alex Christensen
no flags Details | Formatted Diff | Diff
Patch (33.52 KB, patch)
2015-07-17 15:16 PDT, Alex Christensen
no flags Details | Formatted Diff | Diff
Patch (35.67 KB, patch)
2015-07-20 15:41 PDT, Alex Christensen
no flags Details | Formatted Diff | Diff
Patch (35.90 KB, patch)
2015-07-20 15:42 PDT, Alex Christensen
benjamin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Christensen 2015-07-17 14:32:14 PDT
If you have lots of rules with triggers like {"url-filter":".*","if-domain":["*webkit.org"]} we will spend a lot of time adding unnecessary actions to HashSets when you are not on webkit.org.  Caching all the rules and only adding them to a collection once when the domain changes saves a lot of URL interpreting time.
Comment 1 Alex Christensen 2015-07-17 14:39:13 PDT
Created attachment 256991 [details]
Patch
Comment 2 Alex Christensen 2015-07-17 15:14:44 PDT
Created attachment 256996 [details]
Patch
Comment 3 Alex Christensen 2015-07-17 15:16:26 PDT
Created attachment 256998 [details]
Patch
Comment 4 Benjamin Poulain 2015-07-17 18:25:43 PDT
Comment on attachment 256998 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=256998&action=review

I really like your approach in this patch.

I want to double-check the results on device. I am surprised it does not help the runtime more.

> Source/WebCore/contentextensions/ContentExtension.cpp:88
> +            css.append(action.stringArgument());

While not strictly equivalent, it would be better to merge all the selectors and let the style subsystem split them as needed.

> Source/WebCore/contentextensions/ContentExtension.cpp:98
> +    // These actions don't need to be applied individually any more. They will all be applied to every page as a precompiled style sheet.
> +    m_universalActionsWithoutDomains.removeAllMatching(inGlobalDisplayNoneStyleSheet);

All of the computation above should be done when populating m_universalActionsWithoutDomains. Otherwise there is a window between the constructor and ContentExtension::globalDisplayNoneStyleSheet() during which m_universalActionsWithoutDomains has the CSS rules.

After removing all the CSS, you should do m_universalActionsWithoutDomains.shrinkToFit(). That vector will never need to grow again so we can get back as much memory as possible.

> Source/WebCore/contentextensions/ContentExtension.cpp:127
>      }

Could be worth shrinkToFit() both vectors after this.

> Source/WebCore/contentextensions/ContentExtension.cpp:133
> +    ASSERT_WITH_MESSAGE_UNUSED(domain, domain == m_cachedDomain, "universalWithDomains should only be called right after cachedDomainActions with the same domain, so the cache should aways be correct");

This is a bit fragile for the interface.

What about having a new populateCacheIfNeeded(domain) as the first call of universalActionsWithDomains() and cachedDomainActions()?

> Source/WebCore/contentextensions/ContentExtensionCompiler.cpp:-270
> -                if (!ignorePreviousRulesSeen

You can completely remove "ignorePreviousRulesSeen" without this condition.

> Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp:184
> +                if (instruction == DFABytecodeInstruction::AppendAction)
> +                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
> +                else if (instruction == DFABytecodeInstruction::AppendActionWithIfDomain)
> +                    programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfDomain);

It is unfortunate we still need to touch all this memory. The load-store unit is out next bottleneck.

Can you find out how much memory load and skip at the beginning of machines?
Comment 5 Alex Christensen 2015-07-18 08:40:19 PDT
(In reply to comment #4)
> All of the computation above should be done when populating
> m_universalActionsWithoutDomains. Otherwise there is a window between the
> constructor and ContentExtension::globalDisplayNoneStyleSheet() during which
> m_universalActionsWithoutDomains has the CSS rules.
This was intentional to keep the load time low, but we have to do it anyway before loading a page.  I think I'll change this.
> What about having a new populateCacheIfNeeded(domain) as the first call of
> universalActionsWithDomains() and cachedDomainActions()?
This would make an unnecessary string copy of a short string, but I think the stability would be worth it.
> You can completely remove "ignorePreviousRulesSeen" without this condition.
Right.
> Can you find out how much memory load and skip at the beginning of machines?
We could move all these actions into separate "vectors" in the file and never touch it again.
Comment 6 Alex Christensen 2015-07-18 18:47:37 PDT
Comment on attachment 256998 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=256998&action=review

> Source/WebCore/contentextensions/ContentExtension.cpp:50
> +    copyToVector(withoutDomains.actionsMatchingEverything(), m_universalActionsWithoutDomains);

iOS doesn't like this because it's implicitly casting uint64_t's to uint32_t's.  I need to make this into a for loop with an assertion that the casting doesn't lose any information.
Comment 7 Alex Christensen 2015-07-20 15:41:16 PDT
Created attachment 257136 [details]
Patch
Comment 8 Alex Christensen 2015-07-20 15:42:36 PDT
Created attachment 257137 [details]
Patch
Comment 9 Benjamin Poulain 2015-07-20 16:32:42 PDT
Comment on attachment 257137 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=257137&action=review

> Source/WebCore/contentextensions/ContentExtension.cpp:107
> +    css.append(ContentExtensionsBackend::displayNoneCSSRule());

What a waste of CPU cycles :(

> Source/WebCore/contentextensions/ContentExtension.cpp:136
> +        

shrinkToFit() both vectors?

> Source/WebCore/contentextensions/ContentExtensionsBackend.cpp:136
> -    WTFLogAlways("Time added: %f microseconds %s", (addedTimeEnd - addedTimeStart) * 1.0e6, resourceLoadInfo.resourceURL.string().utf8().data());
> +    dataLogF("Time added: %f microseconds %s \n", (addedTimeEnd - addedTimeStart) * 1.0e6, resourceLoadInfo.resourceURL.string().utf8().data());

Am I the only one having trouble with dataLog on device?
Comment 10 Alex Christensen 2015-07-20 17:11:17 PDT
Comment on attachment 257137 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=257137&action=review

>> Source/WebCore/contentextensions/ContentExtension.cpp:136
>> +        
> 
> shrinkToFit() both vectors?

good idea!

>> Source/WebCore/contentextensions/ContentExtensionsBackend.cpp:136
>> +    dataLogF("Time added: %f microseconds %s \n", (addedTimeEnd - addedTimeStart) * 1.0e6, resourceLoadInfo.resourceURL.string().utf8().data());
> 
> Am I the only one having trouble with dataLog on device?

no.  I just reroute dataLogF to WTFLogAlways when debugging on device.  There's probably a better way to do it.
Comment 11 Alex Christensen 2015-07-20 17:13:49 PDT
http://trac.webkit.org/changeset/187049
Comment 12 Alex Christensen 2015-07-20 17:29:42 PDT
Got a little too ambitious with that shrinking and committed build fix to http://trac.webkit.org/changeset/187051
Comment 13 Radar WebKit Bug Importer 2015-07-20 19:29:46 PDT
<rdar://problem/21913164>