UMA histograms to measure whether / how long blank text is rendered for loading web fonts

This patch adds two UMA metrics:

WebFont.BlankTextShownTime histogram tracks the time we spent showing
blank text. This measures the time between when the "loading fallback"
font is drawn for the first time, and when FontData for the downloaded
web font is created.

WebFont.HadBlankText is recorded once per page load if the page uses
any web fonts. The value is 1 if we ended up showing blank text at
least once, 0 otherwise.

BUG=345839
TEST=Manually tested with chrome://histograms

Review URL: https://codereview.chromium.org/180273020

git-svn-id: svn://svn.chromium.org/blink/trunk@168541 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent b1a23750
...@@ -35,6 +35,13 @@ public: ...@@ -35,6 +35,13 @@ public:
virtual ~CSSCustomFontData() { } virtual ~CSSCustomFontData() { }
virtual bool shouldSkipDrawing() const OVERRIDE
{
if (m_fontFaceSource)
m_fontFaceSource->paintRequested();
return m_fallbackVisibility == InvisibleFallback && m_isUsed;
}
virtual void beginLoadIfNeeded() const OVERRIDE virtual void beginLoadIfNeeded() const OVERRIDE
{ {
if (!m_isUsed && m_isLoadingFallback && m_fontFaceSource) { if (!m_isUsed && m_isLoadingFallback && m_fontFaceSource) {
......
...@@ -105,6 +105,8 @@ public: ...@@ -105,6 +105,8 @@ public:
void willUseFontData(const FontDescription&); void willUseFontData(const FontDescription&);
void load(const FontDescription&, CSSFontSelector* = 0); void load(const FontDescription&, CSSFontSelector* = 0);
bool hadBlankText() { return isValid() && m_sources.first()->hadBlankText(); }
private: private:
void setLoadStatus(FontFace::LoadStatus); void setLoadStatus(FontFace::LoadStatus);
......
...@@ -205,6 +205,8 @@ PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& ...@@ -205,6 +205,8 @@ PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription&
if (!m_font->ensureCustomFontData()) if (!m_font->ensureCustomFontData())
return nullptr; return nullptr;
m_histograms.recordFallbackTime(m_font.get());
fontData = SimpleFontData::create( fontData = SimpleFontData::create(
m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(), m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(), fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
...@@ -285,6 +287,12 @@ void CSSFontFaceSource::FontLoadHistograms::loadStarted() ...@@ -285,6 +287,12 @@ void CSSFontFaceSource::FontLoadHistograms::loadStarted()
m_loadStartTime = currentTimeMS(); m_loadStartTime = currentTimeMS();
} }
void CSSFontFaceSource::FontLoadHistograms::fallbackFontPainted()
{
if (!m_fallbackPaintTime)
m_fallbackPaintTime = currentTimeMS();
}
void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess) void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess)
{ {
if (!m_loadStartTime) { if (!m_loadStartTime) {
...@@ -293,6 +301,15 @@ void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess) ...@@ -293,6 +301,15 @@ void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess)
} }
} }
void CSSFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontResource* font)
{
if (m_fallbackPaintTime <= 0)
return;
int duration = static_cast<int>(currentTimeMS() - m_fallbackPaintTime);
blink::Platform::current()->histogramCustomCounts("WebFont.BlankTextShownTime", duration, 0, 10000, 50);
m_fallbackPaintTime = -1;
}
void CSSFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font) void CSSFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font)
{ {
if (m_loadStartTime > 0 && font && !font->isLoading()) { if (m_loadStartTime > 0 && font && !font->isLoading()) {
......
...@@ -74,18 +74,26 @@ public: ...@@ -74,18 +74,26 @@ public:
bool isLocalFontAvailable(const FontDescription&); bool isLocalFontAvailable(const FontDescription&);
void beginLoadIfNeeded(); void beginLoadIfNeeded();
// For UMA reporting
void paintRequested() { m_histograms.fallbackFontPainted(); }
bool hadBlankText() { return m_histograms.hadBlankText(); }
private: private:
typedef HashMap<unsigned, RefPtr<SimpleFontData> > FontDataTable; // The hash key is composed of size synthetic styles. typedef HashMap<unsigned, RefPtr<SimpleFontData> > FontDataTable; // The hash key is composed of size synthetic styles.
class FontLoadHistograms { class FontLoadHistograms {
public: public:
FontLoadHistograms() : m_loadStartTime(0) { } FontLoadHistograms() : m_loadStartTime(0), m_fallbackPaintTime(0) { }
void loadStarted(); void loadStarted();
void fallbackFontPainted();
void recordLocalFont(bool loadSuccess); void recordLocalFont(bool loadSuccess);
void recordRemoteFont(const FontResource*); void recordRemoteFont(const FontResource*);
void recordFallbackTime(const FontResource*);
bool hadBlankText() { return m_fallbackPaintTime; }
private: private:
const char* histogramName(const FontResource*); const char* histogramName(const FontResource*);
double m_loadStartTime; double m_loadStartTime;
double m_fallbackPaintTime;
}; };
void pruneTable(); void pruneTable();
......
...@@ -550,4 +550,9 @@ void FontFace::trace(Visitor* visitor) ...@@ -550,4 +550,9 @@ void FontFace::trace(Visitor* visitor)
visitor->trace(m_featureSettings); visitor->trace(m_featureSettings);
} }
bool FontFace::hadBlankText() const
{
return m_cssFontFace->hadBlankText();
}
} // namespace WebCore } // namespace WebCore
...@@ -87,6 +87,8 @@ public: ...@@ -87,6 +87,8 @@ public:
void trace(Visitor*); void trace(Visitor*);
bool hadBlankText() const;
private: private:
FontFace(PassRefPtrWillBeRawPtr<CSSValue> source); FontFace(PassRefPtrWillBeRawPtr<CSSValue> source);
......
...@@ -173,7 +173,7 @@ void FontFaceSet::handlePendingEventsAndPromisesSoon() ...@@ -173,7 +173,7 @@ void FontFaceSet::handlePendingEventsAndPromisesSoon()
void FontFaceSet::didLayout() void FontFaceSet::didLayout()
{ {
if (document()->frame()->isMainFrame()) if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty())
m_histogram.record(); m_histogram.record();
if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) if (!RuntimeEnabledFeatures::fontLoadEventsEnabled())
return; return;
...@@ -219,6 +219,7 @@ void FontFaceSet::beginFontLoading(FontFace* fontFace) ...@@ -219,6 +219,7 @@ void FontFaceSet::beginFontLoading(FontFace* fontFace)
void FontFaceSet::fontLoaded(FontFace* fontFace) void FontFaceSet::fontLoaded(FontFace* fontFace)
{ {
m_histogram.updateStatus(fontFace);
if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
m_loadedFonts.append(fontFace); m_loadedFonts.append(fontFace);
removeFromLoadingFonts(fontFace); removeFromLoadingFonts(fontFace);
...@@ -226,6 +227,7 @@ void FontFaceSet::fontLoaded(FontFace* fontFace) ...@@ -226,6 +227,7 @@ void FontFaceSet::fontLoaded(FontFace* fontFace)
void FontFaceSet::loadError(FontFace* fontFace) void FontFaceSet::loadError(FontFace* fontFace)
{ {
m_histogram.updateStatus(fontFace);
if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) if (RuntimeEnabledFeatures::fontLoadEventsEnabled())
m_failedFonts.append(fontFace); m_failedFonts.append(fontFace);
removeFromLoadingFonts(fontFace); removeFromLoadingFonts(fontFace);
...@@ -509,12 +511,26 @@ bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) ...@@ -509,12 +511,26 @@ bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font)
return true; return true;
} }
void FontFaceSet::FontLoadHistogram::record() void FontFaceSet::FontLoadHistogram::updateStatus(FontFace* fontFace)
{ {
if (m_recorded) if (m_status == Reported)
return; return;
if (fontFace->hadBlankText())
m_status = HadBlankText;
else if (m_status == NoWebFonts)
m_status = DidNotHaveBlankText;
}
void FontFaceSet::FontLoadHistogram::record()
{
if (!m_recorded) {
m_recorded = true; m_recorded = true;
blink::Platform::current()->histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1, 100, 50); blink::Platform::current()->histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1, 100, 50);
}
if (m_status == HadBlankText || m_status == DidNotHaveBlankText) {
blink::Platform::current()->histogramEnumeration("WebFont.HadBlankText", m_status == HadBlankText ? 1 : 0, 2);
m_status = Reported;
}
} }
static const char* supplementName() static const char* supplementName()
......
...@@ -111,11 +111,14 @@ private: ...@@ -111,11 +111,14 @@ private:
class FontLoadHistogram { class FontLoadHistogram {
public: public:
FontLoadHistogram() : m_count(0), m_recorded(false) { } enum Status { NoWebFonts, HadBlankText, DidNotHaveBlankText, Reported };
FontLoadHistogram() : m_status(NoWebFonts), m_count(0), m_recorded(false) { }
void incrementCount() { m_count++; } void incrementCount() { m_count++; }
void updateStatus(FontFace*);
void record(); void record();
private: private:
Status m_status;
int m_count; int m_count;
bool m_recorded; bool m_recorded;
}; };
......
...@@ -48,7 +48,7 @@ public: ...@@ -48,7 +48,7 @@ public:
virtual void beginLoadIfNeeded() const { }; virtual void beginLoadIfNeeded() const { };
bool isLoading() const { return m_isLoadingFallback && m_isUsed; } bool isLoading() const { return m_isLoadingFallback && m_isUsed; }
bool isLoadingFallback() const { return m_isLoadingFallback; } bool isLoadingFallback() const { return m_isLoadingFallback; }
bool shouldSkipDrawing() const { return m_fallbackVisibility == InvisibleFallback && m_isUsed; } virtual bool shouldSkipDrawing() const { return false; }
virtual bool isSVGFont() const { return false; } virtual bool isSVGFont() const { return false; }
virtual void initializeFontData(SimpleFontData*, float) { } virtual void initializeFontData(SimpleFontData*, float) { }
......
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