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

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: Make parser Settings values unsigned. Assert outstanding>=pending. 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 26 matching lines...) Expand all
37 #include "wtf/text/TextPosition.h" 37 #include "wtf/text/TextPosition.h"
38 38
39 namespace blink { 39 namespace blink {
40 40
41 // On a network with high latency and high bandwidth, using a device 41 // On a network with high latency and high bandwidth, using a device
42 // with a fast CPU, we could end up speculatively tokenizing 42 // with a fast CPU, we could end up speculatively tokenizing
43 // the whole document, well ahead of when the main-thread actually needs it. 43 // 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). 44 // This is a waste of memory (and potentially time if the speculation fails).
45 // So we limit our outstanding tokens arbitrarily to 10,000. 45 // So we limit our outstanding tokens arbitrarily to 10,000.
46 // Our maximal memory spent speculating will be approximately: 46 // Our maximal memory spent speculating will be approximately:
47 // (outstandingTokenLimit + pendingTokenLimit) * sizeof(CompactToken) 47 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) *
48 // sizeof(CompactToken)
48 // We use a separate low and high water mark to avoid constantly topping 49 // We use a separate low and high water mark to avoid constantly topping
49 // off the main thread's token buffer. 50 // off the main thread's token buffer.
50 // At time of writing, this is (10000 + 1000) * 28 bytes = ~308kb of memory. 51 // At time of writing, this is (10000 + 1000) * 28 bytes = ~308kb of memory.
51 // These numbers have not been tuned. 52 // These numbers have not been tuned.
52 static const size_t outstandingTokenLimit = 10000; 53 static const size_t defaultOutstandingTokenLimit = 10000;
53 54
54 // We limit our chucks to 1000 tokens, to make sure the main 55 // We limit our chucks to 1000 tokens, to make sure the main
55 // thread is never waiting on the parser thread for tokens. 56 // thread is never waiting on the parser thread for tokens.
56 // This was tuned in https://bugs.webkit.org/show_bug.cgi?id=110408. 57 // This was tuned in https://bugs.webkit.org/show_bug.cgi?id=110408.
57 static const size_t pendingTokenLimit = 1000; 58 static const size_t defaultPendingTokenLimit = 1000;
58 59
59 using namespace HTMLNames; 60 using namespace HTMLNames;
60 61
61 #if ENABLE(ASSERT) 62 #if ENABLE(ASSERT)
62 63
63 static void checkThatTokensAreSafeToSendToAnotherThread(const CompactHTMLTokenSt ream* tokens) 64 static void checkThatTokensAreSafeToSendToAnotherThread(const CompactHTMLTokenSt ream* tokens)
64 { 65 {
65 for (size_t i = 0; i < tokens->size(); ++i) 66 for (size_t i = 0; i < tokens->size(); ++i)
66 ASSERT(tokens->at(i).isSafeToSendToAnotherThread()); 67 ASSERT(tokens->at(i).isSafeToSendToAnotherThread());
67 } 68 }
(...skipping 11 matching lines...) Expand all
79 } 80 }
80 81
81 #endif 82 #endif
82 83
83 void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler) 84 void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
84 { 85 {
85 new BackgroundHTMLParser(reference, config, scheduler); 86 new BackgroundHTMLParser(reference, config, scheduler);
86 // Caller must free by calling stop(). 87 // Caller must free by calling stop().
87 } 88 }
88 89
90 BackgroundHTMLParser::Configuration::Configuration()
91 : outstandingTokenLimit(defaultOutstandingTokenLimit)
92 , pendingTokenLimit(defaultPendingTokenLimit)
93 {
94 }
95
89 BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHT MLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler) 96 BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHT MLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
90 : m_weakFactory(reference, this) 97 : m_weakFactory(reference, this)
91 , m_token(adoptPtr(new HTMLToken)) 98 , m_token(adoptPtr(new HTMLToken))
92 , m_tokenizer(HTMLTokenizer::create(config->options)) 99 , m_tokenizer(HTMLTokenizer::create(config->options))
93 , m_treeBuilderSimulator(config->options) 100 , m_treeBuilderSimulator(config->options)
94 , m_options(config->options) 101 , m_options(config->options)
102 , m_outstandingTokenLimit(config->outstandingTokenLimit)
95 , m_parser(config->parser) 103 , m_parser(config->parser)
96 , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream)) 104 , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream))
105 , m_pendingTokenLimit(config->pendingTokenLimit)
97 , m_xssAuditor(config->xssAuditor.release()) 106 , m_xssAuditor(config->xssAuditor.release())
98 , m_preloadScanner(config->preloadScanner.release()) 107 , m_preloadScanner(config->preloadScanner.release())
99 , m_decoder(config->decoder.release()) 108 , m_decoder(config->decoder.release())
100 , m_scheduler(scheduler) 109 , m_scheduler(scheduler)
101 , m_startingScript(false) 110 , m_startingScript(false)
102 { 111 {
112 ASSERT(m_outstandingTokenLimit > 0);
113 ASSERT(m_pendingTokenLimit > 0);
114 ASSERT(m_outstandingTokenLimit >= m_pendingTokenLimit);
103 } 115 }
104 116
105 BackgroundHTMLParser::~BackgroundHTMLParser() 117 BackgroundHTMLParser::~BackgroundHTMLParser()
106 { 118 {
107 } 119 }
108 120
109 void BackgroundHTMLParser::appendRawBytesFromParserThread(const char* data, int dataLength) 121 void BackgroundHTMLParser::appendRawBytesFromParserThread(const char* data, int dataLength)
110 { 122 {
111 ASSERT(m_decoder); 123 ASSERT(m_decoder);
112 updateDocument(m_decoder->decode(data, dataLength)); 124 updateDocument(m_decoder->decode(data, dataLength));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 ASSERT(!m_input.current().isClosed()); 210 ASSERT(!m_input.current().isClosed());
199 m_input.append(String(&kEndOfFileMarker, 1)); 211 m_input.append(String(&kEndOfFileMarker, 1));
200 m_input.close(); 212 m_input.close();
201 } 213 }
202 214
203 void BackgroundHTMLParser::pumpTokenizer() 215 void BackgroundHTMLParser::pumpTokenizer()
204 { 216 {
205 HTMLTreeBuilderSimulator::SimulatedToken simulatedToken = HTMLTreeBuilderSim ulator::OtherToken; 217 HTMLTreeBuilderSimulator::SimulatedToken simulatedToken = HTMLTreeBuilderSim ulator::OtherToken;
206 218
207 // No need to start speculating until the main thread has almost caught up. 219 // No need to start speculating until the main thread has almost caught up.
208 if (m_input.totalCheckpointTokenCount() > outstandingTokenLimit) 220 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit)
209 return; 221 return;
210 222
211 while (true) { 223 while (true) {
212 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token); 224 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), *m_token);
213 if (!m_tokenizer->nextToken(m_input.current(), *m_token)) { 225 if (!m_tokenizer->nextToken(m_input.current(), *m_token)) {
214 // We've reached the end of our current input. 226 // We've reached the end of our current input.
215 sendTokensToMainThread(); 227 sendTokensToMainThread();
216 break; 228 break;
217 } 229 }
218 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token); 230 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), *m_token);
(...skipping 16 matching lines...) Expand all
235 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptStart) { 247 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptStart) {
236 sendTokensToMainThread(); 248 sendTokensToMainThread();
237 m_startingScript = true; 249 m_startingScript = true;
238 } 250 }
239 251
240 m_pendingTokens->append(token); 252 m_pendingTokens->append(token);
241 } 253 }
242 254
243 m_token->clear(); 255 m_token->clear();
244 256
245 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptEnd || m_pendingTo kens->size() >= pendingTokenLimit) { 257 if (simulatedToken == HTMLTreeBuilderSimulator::ScriptEnd || m_pendingTo kens->size() >= m_pendingTokenLimit) {
246 sendTokensToMainThread(); 258 sendTokensToMainThread();
247 // If we're far ahead of the main thread, yield for a bit to avoid c onsuming too much memory. 259 // 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) 260 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit)
249 break; 261 break;
250 } 262 }
251 } 263 }
252 } 264 }
253 265
254 void BackgroundHTMLParser::sendTokensToMainThread() 266 void BackgroundHTMLParser::sendTokensToMainThread()
255 { 267 {
256 if (m_pendingTokens->isEmpty()) 268 if (m_pendingTokens->isEmpty())
257 return; 269 return;
258 270
(...skipping 15 matching lines...) Expand all
274 m_startingScript = false; 286 m_startingScript = false;
275 287
276 m_scheduler->postLoadingTask( 288 m_scheduler->postLoadingTask(
277 FROM_HERE, 289 FROM_HERE,
278 new Task(threadSafeBind(&HTMLDocumentParser::didReceiveParsedChunkFromBa ckgroundParser, AllowCrossThreadAccess(m_parser), chunk.release()))); 290 new Task(threadSafeBind(&HTMLDocumentParser::didReceiveParsedChunkFromBa ckgroundParser, AllowCrossThreadAccess(m_parser), chunk.release())));
279 291
280 m_pendingTokens = adoptPtr(new CompactHTMLTokenStream); 292 m_pendingTokens = adoptPtr(new CompactHTMLTokenStream);
281 } 293 }
282 294
283 } 295 }
OLDNEW
« no previous file with comments | « Source/core/html/parser/BackgroundHTMLParser.h ('k') | Source/core/html/parser/HTMLDocumentParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698