Commit a1d023d3 authored by rajendrant's avatar rajendrant Committed by Commit Bot

Record visible load time metric for images

This metric tracks how long the user has to wait for a visible image to
load completely. This metric will help understand how much delay does
lazyload of images incurs users.

Bug: 812684
Change-Id: Ic97c9a192254a2b64d9f2427d8694d6e36759db9
Reviewed-on: https://chromium-review.googlesource.com/831530
Commit-Queue: rajendrant <rajendrant@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarScott Little <sclittle@chromium.org>
Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#539221}
parent 27a33c65
......@@ -33,6 +33,7 @@
#include "core/dom/IncrementLoadEventDelayCount.h"
#include "core/dom/events/Event.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameClient.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/CrossOriginAttribute.h"
......@@ -43,9 +44,11 @@
#include "core/layout/svg/LayoutSVGImage.h"
#include "core/probe/CoreProbes.h"
#include "core/svg/graphics/SVGImage.h"
#include "platform/Histogram.h"
#include "platform/bindings/Microtask.h"
#include "platform/bindings/ScriptState.h"
#include "platform/bindings/V8PerIsolateData.h"
#include "platform/heap/Persistent.h"
#include "platform/loader/fetch/FetchParameters.h"
#include "platform/loader/fetch/MemoryCache.h"
#include "platform/loader/fetch/ResourceFetcher.h"
......@@ -54,11 +57,47 @@
#include "platform/weborigin/SecurityPolicy.h"
#include "platform/wtf/PtrUtil.h"
#include "public/platform/WebClientHintsType.h"
#include "public/platform/WebEffectiveConnectionType.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
namespace blink {
static void RecordImageVisibleLoadTimeHistogram(
WTF::TimeTicks visible_time,
WebEffectiveConnectionType connection_type) {
WTF::TimeDelta visible_load_time = visible_time.is_null()
? WTF::TimeDelta::FromSeconds(0)
: CurrentTimeTicks() - visible_time;
DEFINE_STATIC_LOCAL(CustomCountHistogram, visible_load_time_slow_2g_histogram,
("Blink.VisibleLoadTime.Image.2GSlow", 1, 10000000, 50));
DEFINE_STATIC_LOCAL(CustomCountHistogram, visible_load_time_2g_histogram,
("Blink.VisibleLoadTime.Image.2G", 1, 10000000, 50));
DEFINE_STATIC_LOCAL(CustomCountHistogram, visible_load_time_3g_histogram,
("Blink.VisibleLoadTime.Image.3G", 1, 10000000, 50));
DEFINE_STATIC_LOCAL(CustomCountHistogram, visible_load_time_4g_histogram,
("Blink.VisibleLoadTime.Image.4G", 1, 10000000, 50));
switch (connection_type) {
case WebEffectiveConnectionType::kTypeSlow2G:
visible_load_time_slow_2g_histogram.Count(
visible_load_time.InMilliseconds());
break;
case WebEffectiveConnectionType::kType2G:
visible_load_time_2g_histogram.Count(visible_load_time.InMilliseconds());
break;
case WebEffectiveConnectionType::kType3G:
visible_load_time_3g_histogram.Count(visible_load_time.InMilliseconds());
break;
case WebEffectiveConnectionType::kType4G:
visible_load_time_4g_histogram.Count(visible_load_time.InMilliseconds());
break;
default:
break;
}
}
static ImageLoader::BypassMainWorldBehavior ShouldBypassMainWorldCSP(
ImageLoader* loader) {
DCHECK(loader);
......@@ -145,6 +184,12 @@ ImageLoader::ImageLoader(Element* element)
image_complete_(true),
loading_image_document_(false),
suppress_error_events_(false) {
if (GetElement()->GetExecutionContext()) {
visibility_observer_ = new ElementVisibilityObserver(
element, WTF::BindRepeating(&ImageLoader::OnImageElementVisible,
WrapWeakPersistent(this)));
visibility_observer_->Start();
}
RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this;
}
......@@ -239,6 +284,7 @@ void ImageLoader::Trace(blink::Visitor* visitor) {
visitor->Trace(image_resource_for_image_document_);
visitor->Trace(element_);
visitor->Trace(decode_requests_);
visitor->Trace(visibility_observer_);
}
void ImageLoader::SetImageForTest(ImageResourceContent* new_image) {
......@@ -653,6 +699,15 @@ void ImageLoader::ImageNotifyFinished(ImageResourceContent* resource) {
DispatchDecodeRequestsIfComplete();
if (element_->GetDocument().GetFrame() &&
element_->GetDocument().GetFrame()->Client()) {
RecordImageVisibleLoadTimeHistogram(time_when_first_visible_,
element_->GetDocument()
.GetFrame()
->Client()
->GetEffectiveConnectionType());
}
if (loading_image_document_) {
CHECK(!pending_load_event_.IsActive());
return;
......@@ -796,6 +851,15 @@ void ImageLoader::ElementDidMoveToNewDocument() {
ClearImage();
}
void ImageLoader::OnImageElementVisible(bool visible) {
if (visible) {
DCHECK(time_when_first_visible_.is_null());
time_when_first_visible_ = CurrentTimeTicks();
visibility_observer_->Stop();
visibility_observer_.Clear();
}
}
// Indicates the next available id that we can use to uniquely identify a decode
// request.
uint64_t ImageLoader::DecodeRequest::s_next_request_id_ = 0;
......
......@@ -28,11 +28,13 @@
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/CoreExport.h"
#include "core/dom/ElementVisibilityObserver.h"
#include "core/loader/resource/ImageResource.h"
#include "core/loader/resource/ImageResourceContent.h"
#include "core/loader/resource/ImageResourceObserver.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/HashSet.h"
#include "platform/wtf/Time.h"
#include "platform/wtf/text/AtomicString.h"
#include "public/platform/TaskType.h"
......@@ -164,6 +166,8 @@ class CORE_EXPORT ImageLoader : public GarbageCollectedFinalized<ImageLoader>,
KURL ImageSourceToKURL(AtomicString) const;
void OnImageElementVisible(bool visible);
// Used to determine whether to immediately initiate the load or to schedule a
// microtask.
bool ShouldLoadImmediately(const KURL&) const;
......@@ -183,6 +187,10 @@ class CORE_EXPORT ImageLoader : public GarbageCollectedFinalized<ImageLoader>,
Member<ImageResourceContent> image_content_;
Member<ImageResource> image_resource_for_image_document_;
Member<ElementVisibilityObserver> visibility_observer_;
// The time when the element is first visibile.
WTF::TimeTicks time_when_first_visible_;
AtomicString failed_load_url_;
base::WeakPtr<Task> pending_task_; // owned by Microtask
std::unique_ptr<IncrementLoadEventDelayCount>
......
......@@ -7660,6 +7660,19 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</details>
</histogram>
<histogram base="true" name="Blink.VisibleLoadTime.Image" units="ms">
<!-- Name completed by histogram_suffixes name="Blink.EffectiveConnectionTypes" -->
<owner>rajendrant@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
Tracks how long the user has to wait for a visible image to completely load,
0ms is recorded if the image is already loaded by the time user scrolls to
it. EffectiveConnectionType (2G, 3G, etc) is recorded as suffix to this
histogram.
</summary>
</histogram>
<histogram name="Blink.XHR.setRequestHeader.HeaderValueCategoryInRFC7230"
enum="XMLHttpRequestHeaderValueCategoryInRFC7230">
<obsolete>
......@@ -103334,6 +103347,14 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<affected-histogram name="WebRTC.Stun.BatchSuccessPercent.UnknownNAT"/>
</histogram_suffixes>
<histogram_suffixes name="Blink.EffectiveConnectionTypes" separator=".">
<suffix name="2GSlow"/>
<suffix name="2G"/>
<suffix name="3G"/>
<suffix name="4G"/>
<affected-histogram name="Blink.VisibleLoadTime.Image"/>
</histogram_suffixes>
<histogram_suffixes name="BlinkCanvasDrawImageType" separator=".">
<suffix name="Canvas"/>
<suffix name="ImageBitmap"/>
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