Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: Source/core/html/parser/BackgroundHTMLParser.cpp

Issue 1175183006: Make it possible to modify background HTML parser token limits. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google, Inc. All Rights Reserved. 2 * Copyright (C) 2013 Google, Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 18 matching lines...) Expand all
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/html/parser/HTMLDocumentParser.h" 30 #include "core/html/parser/HTMLDocumentParser.h"
31 #include "core/html/parser/TextResourceDecoder.h" 31 #include "core/html/parser/TextResourceDecoder.h"
32 #include "core/html/parser/XSSAuditor.h" 32 #include "core/html/parser/XSSAuditor.h"
33 #include "platform/Task.h" 33 #include "platform/Task.h"
34 #include "platform/ThreadSafeFunctional.h" 34 #include "platform/ThreadSafeFunctional.h"
35 #include "public/platform/Platform.h" 35 #include "public/platform/Platform.h"
36 #include "public/platform/WebScheduler.h" 36 #include "public/platform/WebScheduler.h"
37 #include "wtf/text/TextPosition.h" 37 #include "wtf/text/TextPosition.h"
38 38
39 #include <algorithm>
40
39 namespace blink { 41 namespace blink {
40 42
41 // On a network with high latency and high bandwidth, using a device 43 // On a network with high latency and high bandwidth, using a device
42 // with a fast CPU, we could end up speculatively tokenizing 44 // with a fast CPU, we could end up speculatively tokenizing
43 // the whole document, well ahead of when the main-thread actually needs it. 45 // the whole document, well ahead of when the main-thread actually needs it.
44 // This is a waste of memory (and potentially time if the speculation fails). 46 // This is a waste of memory (and potentially time if the speculation fails).
45 // So we limit our outstanding tokens arbitrarily to 10,000. 47 // So we limit our outstanding tokens arbitrarily to 10,000.
46 // Our maximal memory spent speculating will be approximately: 48 // Our maximal memory spent speculating will be approximately:
47 // (outstandingTokenLimit + pendingTokenLimit) * sizeof(CompactToken) 49 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) *
50 // sizeof(CompactToken)
48 // We use a separate low and high water mark to avoid constantly topping 51 // We use a separate low and high water mark to avoid constantly topping
49 // off the main thread's token buffer. 52 // off the main thread's token buffer.
50 // At time of writing, this is (10000 + 1000) * 28 bytes = ~308kb of memory. 53 // At time of writing, this is (10000 + 1000) * 28 bytes = ~308kb of memory.
51 // These numbers have not been tuned. 54 // These numbers have not been tuned.
52 static const size_t outstandingTokenLimit = 10000; 55 static const size_t defaultOutstandingTokenLimit = 10000;
53 56
54 // We limit our chucks to 1000 tokens, to make sure the main 57 // We limit our chucks to 1000 tokens, to make sure the main
55 // thread is never waiting on the parser thread for tokens. 58 // thread is never waiting on the parser thread for tokens.
56 // This was tuned in https://bugs.webkit.org/show_bug.cgi?id=110408. 59 // This was tuned in https://bugs.webkit.org/show_bug.cgi?id=110408.
57 static const size_t pendingTokenLimit = 1000; 60 static const size_t defaultPendingTokenLimit = 1000;
58 61
59 using namespace HTMLNames; 62 using namespace HTMLNames;
60 63
61 #if ENABLE(ASSERT) 64 #if ENABLE(ASSERT)
62 65
63 static void checkThatTokensAreSafeToSendToAnotherThread(const CompactHTMLTokenSt ream* tokens) 66 static void checkThatTokensAreSafeToSendToAnotherThread(const CompactHTMLTokenSt ream* tokens)
64 { 67 {
65 for (size_t i = 0; i < tokens->size(); ++i) 68 for (size_t i = 0; i < tokens->size(); ++i)
66 ASSERT(tokens->at(i).isSafeToSendToAnotherThread()); 69 ASSERT(tokens->at(i).isSafeToSendToAnotherThread());
67 } 70 }
(...skipping 11 matching lines...) Expand all
79 } 82 }
80 83
81 #endif 84 #endif
82 85
83 void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler) 86 void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
84 { 87 {
85 new BackgroundHTMLParser(reference, config, scheduler); 88 new BackgroundHTMLParser(reference, config, scheduler);
86 // Caller must free by calling stop(). 89 // Caller must free by calling stop().
87 } 90 }
88 91
92 BackgroundHTMLParser::Configuration::Configuration()
93 : outstandingTokenLimit(defaultOutstandingTokenLimit)
94 , pendingTokenLimit(defaultPendingTokenLimit)
95 {
96 }
97
89 BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHT MLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler) 98 BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHT MLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
90 : m_weakFactory(reference, this) 99 : m_weakFactory(reference, this)
91 , m_token(adoptPtr(new HTMLToken)) 100 , m_token(adoptPtr(new HTMLToken))
92 , m_tokenizer(HTMLTokenizer::create(config->options)) 101 , m_tokenizer(HTMLTokenizer::create(config->options))
93 , m_treeBuilderSimulator(config->options) 102 , m_treeBuilderSimulator(config->options)
94 , m_options(config->options) 103 , m_options(config->options)
104 , m_outstandingTokenLimit(std::max(config->outstandingTokenLimit, config->pe ndingTokenLimit))
Nate Chapin 2015/06/11 18:48:23 Why take the max of the two here? Should we assert
Bryan McQuade 2015/06/12 14:12:59 Yes, that's clearer. Agree. I've made this change.
95 , m_parser(config->parser) 105 , m_parser(config->parser)
96 , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream)) 106 , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream))
107 , m_pendingTokenLimit(config->pendingTokenLimit)
97 , m_xssAuditor(config->xssAuditor.release()) 108 , m_xssAuditor(config->xssAuditor.release())
98 , m_preloadScanner(config->preloadScanner.release()) 109 , m_preloadScanner(config->preloadScanner.release())
99 , m_decoder(config->decoder.release()) 110 , m_decoder(config->decoder.release())
100 , m_scheduler(scheduler) 111 , m_scheduler(scheduler)
101 , m_startingScript(false) 112 , m_startingScript(false)
102 { 113 {
114 ASSERT(m_outstandingTokenLimit > 0);
115 ASSERT(m_pendingTokenLimit > 0);
103 } 116 }
104 117
105 BackgroundHTMLParser::~BackgroundHTMLParser() 118 BackgroundHTMLParser::~BackgroundHTMLParser()
106 { 119 {
107 } 120 }
108 121
109 void BackgroundHTMLParser::appendRawBytesFromParserThread(const char* data, int dataLength) 122 void BackgroundHTMLParser::appendRawBytesFromParserThread(const char* data, int dataLength)
110 { 123 {
111 ASSERT(m_decoder); 124 ASSERT(m_decoder);
112 updateDocument(m_decoder->decode(data, dataLength)); 125 updateDocument(m_decoder->decode(data, dataLength));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 ASSERT(!m_input.current().isClosed()); 211 ASSERT(!m_input.current().isClosed());
199 m_input.append(String(&kEndOfFileMarker, 1)); 212 m_input.append(String(&kEndOfFileMarker, 1));
200 m_input.close(); 213 m_input.close();
201 } 214 }
202 215
203 void BackgroundHTMLParser::pumpTokenizer() 216 void BackgroundHTMLParser::pumpTokenizer()
204 { 217 {
205 HTMLTreeBuilderSimulator::SimulatedToken simulatedToken = HTMLTreeBuilderSim ulator::OtherToken; 218 HTMLTreeBuilderSimulator::SimulatedToken simulatedToken = HTMLTreeBuilderSim ulator::OtherToken;
206 219
207 // No need to start speculating until the main thread has almost caught up. 220 // No need to start speculating until the main thread has almost caught up.
208 if (m_input.totalCheckpointTokenCount() > outstandingTokenLimit) 221 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit)
209 return; 222 return;
210 223
211 while (true) { 224 while (true) {
212 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token); 225 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token);
213 if (!m_tokenizer->nextToken(m_input.current(), *m_token)) { 226 if (!m_tokenizer->nextToken(m_input.current(), *m_token)) {
214 // We've reached the end of our current input. 227 // We've reached the end of our current input.
215 sendTokensToMainThread(); 228 sendTokensToMainThread();
216 break; 229 break;
217 } 230 }
218 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token); 231 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token);
(...skipping 16 matching lines...) Expand all
235 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptStart) { 248 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptStart) {
236 sendTokensToMainThread(); 249 sendTokensToMainThread();
237 m_startingScript = true; 250 m_startingScript = true;
238 } 251 }
239 252
240 m_pendingTokens->append(token); 253 m_pendingTokens->append(token);
241 } 254 }
242 255
243 m_token->clear(); 256 m_token->clear();
244 257
245 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptEnd || m_pendingTo kens->size() >= pendingTokenLimit) { 258 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptEnd || m_pendingTo kens->size() >= m_pendingTokenLimit) {
246 sendTokensToMainThread(); 259 sendTokensToMainThread();
247 // If we're far ahead of the main thread, yield for a bit to avoid c onsuming too much memory. 260 // If we're far ahead of the main thread, yield for a bit to avoid c onsuming too much memory.
248 if (m_input.totalCheckpointTokenCount() > outstandingTokenLimit) 261 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit)
249 break; 262 break;
250 } 263 }
251 } 264 }
252 } 265 }
253 266
254 void BackgroundHTMLParser::sendTokensToMainThread() 267 void BackgroundHTMLParser::sendTokensToMainThread()
255 { 268 {
256 if (m_pendingTokens->isEmpty()) 269 if (m_pendingTokens->isEmpty())
257 return; 270 return;
258 271
(...skipping 15 matching lines...) Expand all
274 m_startingScript = false; 287 m_startingScript = false;
275 288
276 m_scheduler->postLoadingTask( 289 m_scheduler->postLoadingTask(
277 FROM_HERE, 290 FROM_HERE,
278 new Task(threadSafeBind(&HTMLDocumentParser::didReceiveParsedChunkFromBa ckgroundParser, AllowCrossThreadAccess(m_parser), chunk.release()))); 291 new Task(threadSafeBind(&HTMLDocumentParser::didReceiveParsedChunkFromBa ckgroundParser, AllowCrossThreadAccess(m_parser), chunk.release())));
279 292
280 m_pendingTokens = adoptPtr(new CompactHTMLTokenStream); 293 m_pendingTokens = adoptPtr(new CompactHTMLTokenStream);
281 } 294 }
282 295
283 } 296 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698