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