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

Side by Side Diff: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp

Issue 2039673002: Track performance of toBlob and its complete timeout delay (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments Created 4 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 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/html/canvas/CanvasAsyncBlobCreator.h" 5 #include "core/html/canvas/CanvasAsyncBlobCreator.h"
6 6
7 #include "core/fileapi/Blob.h" 7 #include "core/fileapi/Blob.h"
8 #include "platform/Histogram.h"
8 #include "platform/ThreadSafeFunctional.h" 9 #include "platform/ThreadSafeFunctional.h"
9 #include "platform/graphics/ImageBuffer.h" 10 #include "platform/graphics/ImageBuffer.h"
10 #include "platform/image-encoders/JPEGImageEncoder.h" 11 #include "platform/image-encoders/JPEGImageEncoder.h"
11 #include "platform/image-encoders/PNGImageEncoder.h" 12 #include "platform/image-encoders/PNGImageEncoder.h"
12 #include "platform/threading/BackgroundTaskRunner.h" 13 #include "platform/threading/BackgroundTaskRunner.h"
13 #include "public/platform/Platform.h" 14 #include "public/platform/Platform.h"
14 #include "public/platform/WebScheduler.h" 15 #include "public/platform/WebScheduler.h"
15 #include "public/platform/WebTaskRunner.h" 16 #include "public/platform/WebTaskRunner.h"
16 #include "public/platform/WebThread.h" 17 #include "public/platform/WebThread.h"
17 #include "public/platform/WebTraceLocation.h" 18 #include "public/platform/WebTraceLocation.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 } else if (mimeType == "image/webp") { 73 } else if (mimeType == "image/webp") {
73 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp; 74 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp;
74 } else { 75 } else {
75 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported; 76 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported;
76 } 77 }
77 return mimeTypeEnum; 78 return mimeTypeEnum;
78 } 79 }
79 80
80 } // anonymous namespace 81 } // anonymous namespace
81 82
82 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unp remultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCall back* callback) 83 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unp remultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCall back* callback, double startTime)
83 { 84 {
84 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeT ypeStringToEnum(mimeType), size, callback); 85 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeT ypeStringToEnum(mimeType), size, callback, startTime);
85 } 86 }
86 87
87 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeT ype mimeType, const IntSize& size, BlobCallback* callback) 88 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeT ype mimeType, const IntSize& size, BlobCallback* callback, double startTime)
88 : m_data(data) 89 : m_data(data)
89 , m_size(size) 90 , m_size(size)
90 , m_mimeType(mimeType) 91 , m_mimeType(mimeType)
91 , m_callback(callback) 92 , m_callback(callback)
93 , m_startTime(startTime)
92 { 94 {
93 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4)); 95 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4));
94 m_encodedImage = wrapUnique(new Vector<unsigned char>()); 96 m_encodedImage = wrapUnique(new Vector<unsigned char>());
95 m_pixelRowStride = size.width() * NumChannelsPng; 97 m_pixelRowStride = size.width() * NumChannelsPng;
96 m_idleTaskStatus = IdleTaskNotSupported; 98 m_idleTaskStatus = IdleTaskNotSupported;
97 m_numRowsCompleted = 0; 99 m_numRowsCompleted = 0;
98 } 100 }
99 101
100 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() 102 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator()
101 { 103 {
(...skipping 27 matching lines...) Expand all
129 // There's no risk of concurrency as both tasks are on main thread. 131 // There's no risk of concurrency as both tasks are on main thread.
130 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay); 132 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay);
131 } else if (m_mimeType == MimeTypeWebp) { 133 } else if (m_mimeType == MimeTypeWebp) {
132 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa sk : BackgroundTaskRunner::TaskSizeShortRunningTask; 134 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa sk : BackgroundTaskRunner::TaskSizeShortRunningTask;
133 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist ent(this), quality), taskSize); 135 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist ent(this), quality), taskSize);
134 } 136 }
135 } 137 }
136 138
137 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality) 139 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality)
138 { 140 {
141 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
139 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); 142 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality));
140 } 143 }
141 144
142 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double deadlineSeconds) 145 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double deadlineSeconds)
143 { 146 {
144 ASSERT(isMainThread()); 147 ASSERT(isMainThread());
148 m_initiateStartTime = WTF::monotonicallyIncreasingTime();
149 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGInitiateEncodingCounter, ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50));
150 toBlobJPEGInitiateEncodingCounter.count((m_initiateStartTime - m_scheduleIni tiateStartTime) * 1000000.0);
145 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 151 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
146 return; 152 return;
147 } 153 }
148 154
149 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); 155 ASSERT(m_idleTaskStatus == IdleTaskNotStarted);
150 m_idleTaskStatus = IdleTaskStarted; 156 m_idleTaskStatus = IdleTaskStarted;
151 157
152 if (!initializeJpegStruct(quality)) { 158 if (!initializeJpegStruct(quality)) {
153 m_idleTaskStatus = IdleTaskFailed; 159 m_idleTaskStatus = IdleTaskFailed;
154 return; 160 return;
155 } 161 }
156 this->idleEncodeRowsJpeg(deadlineSeconds); 162 this->idleEncodeRowsJpeg(deadlineSeconds);
157 } 163 }
158 164
159 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() 165 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding()
160 { 166 {
167 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
161 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); 168 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE , bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this));
162 } 169 }
163 170
164 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) 171 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds)
165 { 172 {
166 ASSERT(isMainThread()); 173 ASSERT(isMainThread());
174 m_initiateStartTime = WTF::monotonicallyIncreasingTime();
175 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGInitiateEncodingCounter, ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50));
176 toBlobPNGInitiateEncodingCounter.count((m_initiateStartTime - m_scheduleInit iateStartTime) * 1000000.0);
167 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 177 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
168 return; 178 return;
169 } 179 }
170 180
171 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); 181 ASSERT(m_idleTaskStatus == IdleTaskNotStarted);
172 m_idleTaskStatus = IdleTaskStarted; 182 m_idleTaskStatus = IdleTaskStarted;
173 183
174 if (!initializePngStruct()) { 184 if (!initializePngStruct()) {
175 m_idleTaskStatus = IdleTaskFailed; 185 m_idleTaskStatus = IdleTaskFailed;
176 return; 186 return;
(...skipping 17 matching lines...) Expand all
194 } 204 }
195 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get()); 205 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get());
196 inputPixels += m_pixelRowStride; 206 inputPixels += m_pixelRowStride;
197 } 207 }
198 m_numRowsCompleted = m_size.height(); 208 m_numRowsCompleted = m_size.height();
199 PNGImageEncoder::finalizePng(m_pngEncoderState.get()); 209 PNGImageEncoder::finalizePng(m_pngEncoderState.get());
200 210
201 m_idleTaskStatus = IdleTaskCompleted; 211 m_idleTaskStatus = IdleTaskCompleted;
202 212
203 if (isDeadlineNearOrPassed(deadlineSeconds)) { 213 if (isDeadlineNearOrPassed(deadlineSeconds)) {
214 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - m_initiateStartTi me);
Justin Novosad 2016/06/22 14:38:57 At each Idle slice, you are adding the time since
xidachen 2016/06/22 15:40:41 The new patch should have that fixed.
204 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR OM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); 215 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR OM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this));
205 } else { 216 } else {
217 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGIdleEncodeCounter, (" Blink.Canvas.ToBlob.IdleEncodeDuration.PNG", 0, 10000000, 50));
218 toBlobPNGIdleEncodeCounter.count(m_elapsedTime * 1000000.0);
206 this->createBlobAndInvokeCallback(); 219 this->createBlobAndInvokeCallback();
207 } 220 }
208 } 221 }
209 222
210 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) 223 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds)
211 { 224 {
212 ASSERT(isMainThread()); 225 ASSERT(isMainThread());
213 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 226 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
214 return; 227 return;
215 } 228 }
216 229
217 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper(m_jpe gEncoderState.get(), m_data->data(), m_numRowsCompleted, SlackBeforeDeadline, de adlineSeconds); 230 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper(m_jpe gEncoderState.get(), m_data->data(), m_numRowsCompleted, SlackBeforeDeadline, de adlineSeconds);
218 if (m_numRowsCompleted == m_size.height()) { 231 if (m_numRowsCompleted == m_size.height()) {
219 m_idleTaskStatus = IdleTaskCompleted; 232 m_idleTaskStatus = IdleTaskCompleted;
220 if (isDeadlineNearOrPassed(deadlineSeconds)) { 233 if (isDeadlineNearOrPassed(deadlineSeconds)) {
234 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - m_initiateSta rtTime);
Justin Novosad 2016/06/22 14:38:57 Not correct.
221 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLIN K_FROM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this)); 235 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLIN K_FROM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, this));
222 } else { 236 } else {
237 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGIdleEncodeCounte r, ("Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50));
238 toBlobJPEGIdleEncodeCounter.count(m_elapsedTime * 1000000.0);
223 this->createBlobAndInvokeCallback(); 239 this->createBlobAndInvokeCallback();
224 } 240 }
225 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) { 241 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) {
226 m_idleTaskStatus = IdleTaskFailed; 242 m_idleTaskStatus = IdleTaskFailed;
227 this->createNullAndInvokeCallback(); 243 this->createNullAndInvokeCallback();
228 } else { 244 } else {
229 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FR OM_HERE, bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg, this)); 245 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FR OM_HERE, bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg, this));
230 } 246 }
231 } 247 }
232 248
(...skipping 23 matching lines...) Expand all
256 } else { 272 } else {
257 this->createNullAndInvokeCallback(); 273 this->createNullAndInvokeCallback();
258 } 274 }
259 275
260 this->signalAlternativeCodePathFinishedForTesting(); 276 this->signalAlternativeCodePathFinishedForTesting();
261 } 277 }
262 278
263 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() 279 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback()
264 { 280 {
265 ASSERT(isMainThread()); 281 ASSERT(isMainThread());
282 DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus, ("Blink.Canv as.ToBlob.IdleTaskStatus", IdleTaskNotSupported));
xidachen 2016/06/22 14:01:25 xlai@: you are correct. I change the enum histogra
283 toBlobIdleTaskStatus.count(m_idleTaskStatus);
284
285 double elapsedTime = WTF::monotonicallyIncreasingTime() - m_startTime;
286 if (m_mimeType == MimeTypePng) {
287 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGCounter, ("Blink.Canv as.ToBlobDuration.PNG", 0, 10000000, 50));
288 toBlobPNGCounter.count(elapsedTime * 1000000.0);
289 } else if (m_mimeType == MimeTypeJpeg) {
290 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGCounter, ("Blink.Can vas.ToBlobDuration.JPEG", 0, 10000000, 50));
291 toBlobJPEGCounter.count(elapsedTime * 1000000.0);
292 } else {
293 DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobWEBPCounter, ("Blink.Can vas.ToBlobDuration.WEBP", 0, 10000000, 50));
294 toBlobWEBPCounter.count(elapsedTime * 1000000.0);
295 }
266 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size (), convertMimeTypeEnumToString(m_mimeType)); 296 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size (), convertMimeTypeEnumToString(m_mimeType));
267 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob)); 297 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob));
268 // Avoid unwanted retention, see dispose(). 298 // Avoid unwanted retention, see dispose().
269 dispose(); 299 dispose();
270 } 300 }
271 301
272 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() 302 void CanvasAsyncBlobCreator::createNullAndInvokeCallback()
273 { 303 {
274 ASSERT(isMainThread()); 304 ASSERT(isMainThread());
275 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); 305 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 Platform::current()->mainThread()->getWebTaskRunner()->postTask( BLINK_FROM_HERE, bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, this) ); 365 Platform::current()->mainThread()->getWebTaskRunner()->postTask( BLINK_FROM_HERE, bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, this) );
336 } else { 366 } else {
337 // Failing in initialization of jpeg struct 367 // Failing in initialization of jpeg struct
338 this->signalAlternativeCodePathFinishedForTesting(); 368 this->signalAlternativeCodePathFinishedForTesting();
339 } 369 }
340 } 370 }
341 } else { 371 } else {
342 ASSERT(m_idleTaskStatus == IdleTaskFailed || m_idleTaskStatus == IdleTas kCompleted); 372 ASSERT(m_idleTaskStatus == IdleTaskFailed || m_idleTaskStatus == IdleTas kCompleted);
343 this->signalAlternativeCodePathFinishedForTesting(); 373 this->signalAlternativeCodePathFinishedForTesting();
344 } 374 }
345
346 } 375 }
347 376
348 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() 377 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent()
349 { 378 {
350 ASSERT(m_idleTaskStatus != IdleTaskNotStarted); 379 ASSERT(m_idleTaskStatus != IdleTaskNotStarted);
351 380
352 if (m_idleTaskStatus == IdleTaskStarted) { 381 if (m_idleTaskStatus == IdleTaskStarted) {
353 // It has taken too long to complete for the idle task. 382 // It has taken too long to complete for the idle task.
354 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask; 383 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask;
355 signalTaskSwitchInCompleteTimeoutEventForTesting(); 384 signalTaskSwitchInCompleteTimeoutEventForTesting();
(...skipping 10 matching lines...) Expand all
366 } 395 }
367 } 396 }
368 397
369 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation& location, std::unique_ptr<SameThreadClosure> task, double delayMs) 398 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation& location, std::unique_ptr<SameThreadClosure> task, double delayMs)
370 { 399 {
371 DCHECK(isMainThread()); 400 DCHECK(isMainThread());
372 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat ion, std::move(task), delayMs); 401 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat ion, std::move(task), delayMs);
373 } 402 }
374 403
375 } // namespace blink 404 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698