Commit 5fd55ddd authored by Mason Freed's avatar Mason Freed Committed by Commit Bot

Allow Finch control of tokenization budget

The synchronous parser previously had a fixed token budget. This CL
enables Finch experimentation on the number of tokens for that budget.
If no Finch is enabled, the budget stays the same, 500.

Bug: 1128608
Change-Id: I5a0d21833a3b254188dce86fc019a494ce3e3dd0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412827Reviewed-by: default avatarRichard Townsend <richard.townsend@arm.com>
Commit-Queue: Mason Freed <masonfreed@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808483}
parent adfa20c4
...@@ -80,12 +80,12 @@ size_t GetDiscardedTokenCountForTesting() { ...@@ -80,12 +80,12 @@ size_t GetDiscardedTokenCountForTesting() {
return g_discarded_token_count_for_testing; return g_discarded_token_count_for_testing;
} }
// This sets the maximum number of tokens which the foreground HTML parser // This sets the (default) maximum number of tokens which the foreground HTML
// should try to process in one go. Lower values generally mean faster first // parser should try to process in one go. Lower values generally mean faster
// paints, larger values delay first paint, but make sure it's closer to the // first paints, larger values delay first paint, but make sure it's closer to
// final page. This value gives a good speedup, but may need to be tuned // the final page. This is the default value to use, if no Finch-provided
// further. // value exists.
constexpr int kMaxTokenizationBudget = 500; constexpr int kDefaultMaxTokenizationBudget = 500;
// This class encapsulates the internal state needed for synchronous foreground // This class encapsulates the internal state needed for synchronous foreground
// HTML parsing (e.g. if HTMLDocumentParser::PumpTokenizer yields, this class // HTML parsing (e.g. if HTMLDocumentParser::PumpTokenizer yields, this class
...@@ -319,6 +319,10 @@ HTMLDocumentParser::HTMLDocumentParser(Document& document, ...@@ -319,6 +319,10 @@ HTMLDocumentParser::HTMLDocumentParser(Document& document,
document.UkmSourceID(), document.UkmRecorder()); document.UkmSourceID(), document.UkmRecorder());
} }
max_tokenization_budget_ = base::GetFieldTrialParamByFeatureAsInt(
features::kForceSynchronousHTMLParsing, "MaxTokenizationBudget",
kDefaultMaxTokenizationBudget);
// Don't create preloader for parsing clipboard content. // Don't create preloader for parsing clipboard content.
if (content_policy == kDisallowScriptingAndPluginContent) if (content_policy == kDisallowScriptingAndPluginContent)
return; return;
...@@ -889,7 +893,7 @@ bool HTMLDocumentParser::PumpTokenizer() { ...@@ -889,7 +893,7 @@ bool HTMLDocumentParser::PumpTokenizer() {
probe::ParseHTML probe(GetDocument(), this); probe::ParseHTML probe(GetDocument(), this);
bool should_yield = false; bool should_yield = false;
int budget = kMaxTokenizationBudget; int budget = max_tokenization_budget_;
while (CanTakeNextToken() && !should_yield) { while (CanTakeNextToken() && !should_yield) {
{ {
......
...@@ -140,6 +140,10 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser, ...@@ -140,6 +140,10 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
void Flush() final; void Flush() final;
void SetDecoder(std::unique_ptr<TextResourceDecoder>) final; void SetDecoder(std::unique_ptr<TextResourceDecoder>) final;
void SetMaxTokenizationBudgetForTesting(int budget) {
max_tokenization_budget_ = budget;
}
protected: protected:
void insert(const String&) final; void insert(const String&) final;
void Append(const String&) override; void Append(const String&) override;
...@@ -278,6 +282,7 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser, ...@@ -278,6 +282,7 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
// would require keeping track of token positions of preload requests. // would require keeping track of token positions of preload requests.
CompactHTMLToken* pending_csp_meta_token_; CompactHTMLToken* pending_csp_meta_token_;
int max_tokenization_budget_;
bool can_parse_asynchronously_; bool can_parse_asynchronously_;
bool end_was_delayed_; bool end_was_delayed_;
bool have_background_parser_; bool have_background_parser_;
......
...@@ -31,27 +31,31 @@ class MockPrerendererClient : public PrerendererClient { ...@@ -31,27 +31,31 @@ class MockPrerendererClient : public PrerendererClient {
class HTMLDocumentParserTest class HTMLDocumentParserTest
: public PageTestBase, : public PageTestBase,
public testing::WithParamInterface<ParserSynchronizationPolicy> { public testing::WithParamInterface<
testing::tuple<ParserSynchronizationPolicy, int>> {
protected: protected:
void SetUp() override { void SetUp() override {
PageTestBase::SetUp(); PageTestBase::SetUp();
GetDocument().SetURL(KURL("https://example.test")); GetDocument().SetURL(KURL("https://example.test"));
if (GetParam() == ParserSynchronizationPolicy::kForceSynchronousParsing) {
ParserSynchronizationPolicy policy = testing::get<0>(GetParam());
if (policy == ParserSynchronizationPolicy::kForceSynchronousParsing) {
Document::SetThreadedParsingEnabledForTesting(false); Document::SetThreadedParsingEnabledForTesting(false);
} else { } else {
Document::SetThreadedParsingEnabledForTesting(true); Document::SetThreadedParsingEnabledForTesting(true);
} }
if (GetParam() == ParserSynchronizationPolicy::kAllowDeferredParsing) { if (policy == ParserSynchronizationPolicy::kAllowDeferredParsing) {
RuntimeEnabledFeatures::SetForceSynchronousHTMLParsingEnabled(true); RuntimeEnabledFeatures::SetForceSynchronousHTMLParsingEnabled(true);
} else if (GetParam() == } else if (policy ==
ParserSynchronizationPolicy::kAllowAsynchronousParsing) { ParserSynchronizationPolicy::kAllowAsynchronousParsing) {
RuntimeEnabledFeatures::SetForceSynchronousHTMLParsingEnabled(false); RuntimeEnabledFeatures::SetForceSynchronousHTMLParsingEnabled(false);
} }
} }
HTMLDocumentParser* CreateParser(HTMLDocument& document) { HTMLDocumentParser* CreateParser(HTMLDocument& document) {
auto* parser = auto* parser = MakeGarbageCollected<HTMLDocumentParser>(
MakeGarbageCollected<HTMLDocumentParser>(document, GetParam()); document, testing::get<0>(GetParam()));
parser->SetMaxTokenizationBudgetForTesting(testing::get<1>(GetParam()));
std::unique_ptr<TextResourceDecoder> decoder( std::unique_ptr<TextResourceDecoder> decoder(
BuildTextResourceDecoderFor(&document, "text/html", g_null_atom)); BuildTextResourceDecoderFor(&document, "text/html", g_null_atom));
parser->SetDecoder(std::move(decoder)); parser->SetDecoder(std::move(decoder));
...@@ -61,10 +65,12 @@ class HTMLDocumentParserTest ...@@ -61,10 +65,12 @@ class HTMLDocumentParserTest
} // namespace } // namespace
INSTANTIATE_TEST_SUITE_P(HTMLDocumentParserTest, INSTANTIATE_TEST_SUITE_P(
HTMLDocumentParserTest, HTMLDocumentParserTest,
testing::Values(kForceSynchronousParsing, HTMLDocumentParserTest,
kAllowDeferredParsing)); testing::Combine(testing::Values(kForceSynchronousParsing,
kAllowDeferredParsing),
testing::Values(250, 500, 1000)));
TEST_P(HTMLDocumentParserTest, StopThenPrepareToStopShouldNotCrash) { TEST_P(HTMLDocumentParserTest, StopThenPrepareToStopShouldNotCrash) {
auto& document = To<HTMLDocument>(GetDocument()); auto& document = To<HTMLDocument>(GetDocument());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment