Commit 32623381 authored by Dominik Röttsches's avatar Dominik Röttsches Committed by Commit Bot

Experimentally raise font scanning timeout to 2,5 minutes

Font scanning and lookup table construction is only required for font
local matching pre Windows 10. If the timeout is hit, no local font
matching will be performed on this particular pre Win 10
system. Previously we had this set to 15 seconds, which did mean
timeouts on a number of systems, but also previously the render was
waiting synchronously for a result, which is no longer the case.
Experimentally raise this to 150 to see what scanning times are occuring
in the field.

Since the renderer is no longer synchronously waiting, in order to avoid
startup jank due to contention, reduce priority to BEST_EFFORT.

Currently only active behind an experiment configuration.

Bug: 889864, 931366
Change-Id: I19da2ef1e826b8c72a7ea6f0d22814e3e1c35366
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1581627
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#654844}
parent 04f33f2f
...@@ -46,19 +46,21 @@ namespace { ...@@ -46,19 +46,21 @@ namespace {
const base::FilePath::CharType kProtobufFilename[] = const base::FilePath::CharType kProtobufFilename[] =
FILE_PATH_LITERAL("font_unique_name_table.pb"); FILE_PATH_LITERAL("font_unique_name_table.pb");
// The unresponsive renderer timeout is 30 seconds (kDefaultCommitTimeout). As a // Timeout after which font scanning and metadata extraction is stopped and the
// starting point, let's set the max time for indexing fonts to half of that 15 // local lookup table is cleared. Font scanning and lookup table construction is
// seconds. We're starting the font lookup table construction earlier at startup // only needed pre Windows 10. If the timeout is hit, no local font matching
// before a renderer requests this. Once we have more UMA data, we can look // will be performed on this particular pre Win 10 system. Previously we had
// into performance details and reducing this timeout. This timeout is meant to // this set to 15 seconds, which did mean timeouts on a number of systems, but
// cover pathological cases of font indexing where a Windows installation has an // also previously the render was waiting synchronously for a result, which is
// unusually large collection of fonts. In practice, building the unique font // no longer the case. Experimentally raise this to 150 to see what scanning
// name table should not take longer than tens of milliseconds (~26 ms on a // times are occurring in the field.
// developer machine, Windows 10, default fonts). constexpr base::TimeDelta kFontIndexingTimeoutDefault =
const base::TimeDelta kFontIndexingTimeout = base::TimeDelta::FromSeconds(15); base::TimeDelta::FromSeconds(150);
const base::TimeDelta kIndexingSlowDownForTesting = // In timeout test case, slow down indexing of one font file to this percentage
base::TimeDelta::FromMilliseconds(1200); // of the timeout value. Assuming that at least two fonts are indexed, the
// timeout should be usually hit during indexing the second font.
constexpr float kIndexingSlowDownForTestingPercentage = 0.75;
bool ExtractCaseFoldedLocalizedStrings( bool ExtractCaseFoldedLocalizedStrings(
IDWriteLocalizedStrings* dwrite_localized_strings, IDWriteLocalizedStrings* dwrite_localized_strings,
...@@ -128,7 +130,8 @@ DWriteFontLookupTableBuilder::FontFileWithUniqueNames:: ...@@ -128,7 +130,8 @@ DWriteFontLookupTableBuilder::FontFileWithUniqueNames::
DWriteFontLookupTableBuilder::FontFileWithUniqueNames::FontFileWithUniqueNames( DWriteFontLookupTableBuilder::FontFileWithUniqueNames::FontFileWithUniqueNames(
DWriteFontLookupTableBuilder::FontFileWithUniqueNames&& other) = default; DWriteFontLookupTableBuilder::FontFileWithUniqueNames&& other) = default;
DWriteFontLookupTableBuilder::DWriteFontLookupTableBuilder() { DWriteFontLookupTableBuilder::DWriteFontLookupTableBuilder()
: font_indexing_timeout_(kFontIndexingTimeoutDefault) {
// In FontUniqueNameBrowserTest the DWriteFontLookupTableBuilder is // In FontUniqueNameBrowserTest the DWriteFontLookupTableBuilder is
// instantiated to configure the cache directory for testing explicitly before // instantiated to configure the cache directory for testing explicitly before
// GetContentClient() is available. Catch this case here. It is safe to not // GetContentClient() is available. Catch this case here. It is safe to not
...@@ -243,6 +246,10 @@ void DWriteFontLookupTableBuilder::OverrideDWriteVersionChecksForTesting() { ...@@ -243,6 +246,10 @@ void DWriteFontLookupTableBuilder::OverrideDWriteVersionChecksForTesting() {
factory3_.Reset(); factory3_.Reset();
} }
base::TimeDelta DWriteFontLookupTableBuilder::IndexingTimeout() {
return font_indexing_timeout_;
}
base::FilePath DWriteFontLookupTableBuilder::TableCacheFilePath() { base::FilePath DWriteFontLookupTableBuilder::TableCacheFilePath() {
if (!EnsureCacheDirectory(cache_directory_)) if (!EnsureCacheDirectory(cache_directory_))
return base::FilePath(); return base::FilePath();
...@@ -344,13 +351,9 @@ void DWriteFontLookupTableBuilder:: ...@@ -344,13 +351,9 @@ void DWriteFontLookupTableBuilder::
start_time_table_ready_ = base::TimeTicks::Now(); start_time_table_ready_ = base::TimeTicks::Now();
// TODO(https://crbug.com/931366): Downgrade the priority of this startup
// task once the UpdatePriority() API for sequenced task runners is in
// place. Then bump the priority when the renderer needs the table to be
// ready.
scoped_refptr<base::SequencedTaskRunner> results_collection_task_runner = scoped_refptr<base::SequencedTaskRunner> results_collection_task_runner =
base::CreateSequencedTaskRunnerWithTraits( base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING, {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
results_collection_task_runner->PostTask( results_collection_task_runner->PostTask(
...@@ -411,7 +414,7 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() { ...@@ -411,7 +414,7 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
&DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily, &DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily,
collection_, family_index, start_time_table_build_, collection_, family_index, start_time_table_build_,
slow_down_mode_for_testing_, slow_down_mode_for_testing_,
OptionalOrNullptr(hang_event_for_testing_)), OptionalOrNullptr(hang_event_for_testing_), IndexingTimeout()),
base::BindOnce(&DWriteFontLookupTableBuilder:: base::BindOnce(&DWriteFontLookupTableBuilder::
AppendFamilyResultAndFinalizeIfNeeded, AppendFamilyResultAndFinalizeIfNeeded,
base::Unretained(this))); base::Unretained(this)));
...@@ -421,7 +424,7 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() { ...@@ -421,7 +424,7 @@ void DWriteFontLookupTableBuilder::PrepareFontUniqueNameTable() {
timeout_callback_.Reset(base::BindOnce( timeout_callback_.Reset(base::BindOnce(
&DWriteFontLookupTableBuilder::OnTimeout, base::Unretained(this))); &DWriteFontLookupTableBuilder::OnTimeout, base::Unretained(this)));
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, timeout_callback_.callback(), kFontIndexingTimeout); FROM_HERE, timeout_callback_.callback(), IndexingTimeout());
} }
// static // static
...@@ -431,7 +434,8 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily( ...@@ -431,7 +434,8 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
uint32_t family_index, uint32_t family_index,
base::TimeTicks start_time, base::TimeTicks start_time,
SlowDownMode slow_down_mode_for_testing, SlowDownMode slow_down_mode_for_testing,
base::WaitableEvent* hang_event_for_testing) { base::WaitableEvent* hang_event_for_testing,
base::TimeDelta indexing_timeout) {
TRACE_EVENT0("dwrite,fonts", TRACE_EVENT0("dwrite,fonts",
"DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily"); "DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily");
...@@ -440,8 +444,9 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily( ...@@ -440,8 +444,9 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
DWriteFontLookupTableBuilder::FamilyResult family_result; DWriteFontLookupTableBuilder::FamilyResult family_result;
if (base::TimeTicks::Now() - start_time > kFontIndexingTimeout) if (base::TimeTicks::Now() - start_time > indexing_timeout) {
return family_result; return family_result;
}
Microsoft::WRL::ComPtr<IDWriteFontFamily> family; Microsoft::WRL::ComPtr<IDWriteFontFamily> family;
HRESULT hr = collection->GetFontFamily(family_index, &family); HRESULT hr = collection->GetFontFamily(family_index, &family);
...@@ -451,6 +456,10 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily( ...@@ -451,6 +456,10 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
UINT32 font_count = family->GetFontCount(); UINT32 font_count = family->GetFontCount();
for (UINT32 font_index = 0; font_index < font_count; ++font_index) { for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
if (base::TimeTicks::Now() - start_time > indexing_timeout) {
return DWriteFontLookupTableBuilder::FamilyResult();
}
Microsoft::WRL::ComPtr<IDWriteFont> font; Microsoft::WRL::ComPtr<IDWriteFont> font;
{ {
base::ScopedBlockingCall scoped_blocking_call( base::ScopedBlockingCall scoped_blocking_call(
...@@ -521,11 +530,12 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily( ...@@ -521,11 +530,12 @@ DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily(
extract_names(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME); extract_names(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME);
extract_names(DWRITE_INFORMATIONAL_STRING_FULL_NAME); extract_names(DWRITE_INFORMATIONAL_STRING_FULL_NAME);
if (UNLIKELY(slow_down_mode_for_testing == SlowDownMode::kDelayEachTask)) if (UNLIKELY(slow_down_mode_for_testing == SlowDownMode::kDelayEachTask)) {
base::PlatformThread::Sleep(kIndexingSlowDownForTesting); base::PlatformThread::Sleep(indexing_timeout *
else if (UNLIKELY(slow_down_mode_for_testing == kIndexingSlowDownForTestingPercentage);
SlowDownMode::kHangOneTask) && } else if (UNLIKELY(slow_down_mode_for_testing ==
family_index == 0) { SlowDownMode::kHangOneTask) &&
family_index == 0) {
base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_sync_; base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_sync_;
DCHECK(hang_event_for_testing); DCHECK(hang_event_for_testing);
hang_event_for_testing->Wait(); hang_event_for_testing->Wait();
...@@ -591,7 +601,7 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() { ...@@ -591,7 +601,7 @@ void DWriteFontLookupTableBuilder::FinalizeFontTable() {
std::move(font_unique_name_table_)); std::move(font_unique_name_table_));
bool timed_out = false; bool timed_out = false;
if (base::TimeTicks::Now() - start_time_table_build_ > kFontIndexingTimeout) { if (base::TimeTicks::Now() - start_time_table_build_ > IndexingTimeout()) {
font_unique_name_table->clear_fonts(); font_unique_name_table->clear_fonts();
font_unique_name_table->clear_name_map(); font_unique_name_table->clear_name_map();
timed_out = true; timed_out = true;
...@@ -655,15 +665,18 @@ void DWriteFontLookupTableBuilder::OnTimeout() { ...@@ -655,15 +665,18 @@ void DWriteFontLookupTableBuilder::OnTimeout() {
FinalizeFontTable(); FinalizeFontTable();
} }
void DWriteFontLookupTableBuilder::SetSlowDownIndexingForTesting( void DWriteFontLookupTableBuilder::SetSlowDownIndexingForTestingWithTimeout(
SlowDownMode slow_down_mode) { SlowDownMode slow_down_mode,
base::TimeDelta new_timeout) {
slow_down_mode_for_testing_ = slow_down_mode; slow_down_mode_for_testing_ = slow_down_mode;
font_indexing_timeout_ = new_timeout;
if (slow_down_mode == SlowDownMode::kHangOneTask) if (slow_down_mode == SlowDownMode::kHangOneTask)
hang_event_for_testing_.emplace(); hang_event_for_testing_.emplace();
} }
void DWriteFontLookupTableBuilder::ResetLookupTableForTesting() { void DWriteFontLookupTableBuilder::ResetLookupTableForTesting() {
slow_down_mode_for_testing_ = SlowDownMode::kNoSlowdown; slow_down_mode_for_testing_ = SlowDownMode::kNoSlowdown;
font_indexing_timeout_ = kFontIndexingTimeoutDefault;
font_table_memory_ = base::MappedReadOnlyRegion(); font_table_memory_ = base::MappedReadOnlyRegion();
caching_enabled_ = true; caching_enabled_ = true;
font_table_built_.Reset(); font_table_built_.Reset();
......
...@@ -66,8 +66,12 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder { ...@@ -66,8 +66,12 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
enum class SlowDownMode { kDelayEachTask, kHangOneTask, kNoSlowdown }; enum class SlowDownMode { kDelayEachTask, kHangOneTask, kNoSlowdown };
// Slow down each family indexing step for testing the internal timeout. // Slow down each family indexing step for testing the internal timeout,
void SetSlowDownIndexingForTesting(SlowDownMode slowdown_mode); // either with a single hung task or by delaying each indexing step. At the
// same time, configure a new timeout value for testing, overriding the
// default timeout.
void SetSlowDownIndexingForTestingWithTimeout(SlowDownMode slowdown_mode,
base::TimeDelta new_timeout);
// Needed to trigger rebuilding the lookup table, when testing using // Needed to trigger rebuilding the lookup table, when testing using
// slowed-down indexing. Otherwise, the test methods would use the already // slowed-down indexing. Otherwise, the test methods would use the already
...@@ -136,7 +140,8 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder { ...@@ -136,7 +140,8 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
uint32_t family_index, uint32_t family_index,
base::TimeTicks start_time, base::TimeTicks start_time,
SlowDownMode slow_down_mode, SlowDownMode slow_down_mode,
base::WaitableEvent* hang_event_for_testing); base::WaitableEvent* hang_event_for_testing,
base::TimeDelta indexing_timeout);
// Callback from scheduled tasks to add the retrieved font names to the // Callback from scheduled tasks to add the retrieved font names to the
// protobuf. // protobuf.
...@@ -160,6 +165,8 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder { ...@@ -160,6 +165,8 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
// and full font name, in which case we do not need to build this table. // and full font name, in which case we do not need to build this table.
bool HasDWriteUniqueFontLookups(); bool HasDWriteUniqueFontLookups();
base::TimeDelta IndexingTimeout();
DWriteFontLookupTableBuilder(); DWriteFontLookupTableBuilder();
~DWriteFontLookupTableBuilder(); ~DWriteFontLookupTableBuilder();
...@@ -170,6 +177,7 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder { ...@@ -170,6 +177,7 @@ class CONTENT_EXPORT DWriteFontLookupTableBuilder {
base::WaitableEvent font_table_built_; base::WaitableEvent font_table_built_;
bool direct_write_initialized_ = false; bool direct_write_initialized_ = false;
base::TimeDelta font_indexing_timeout_;
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_; Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_;
Microsoft::WRL::ComPtr<IDWriteFactory2> factory2_; Microsoft::WRL::ComPtr<IDWriteFactory2> factory2_;
Microsoft::WRL::ComPtr<IDWriteFactory3> factory3_; Microsoft::WRL::ComPtr<IDWriteFactory3> factory3_;
......
...@@ -32,6 +32,8 @@ constexpr FontExpectation kExpectedTestFonts[] = {{u8"CambriaMath", 1}, ...@@ -32,6 +32,8 @@ constexpr FontExpectation kExpectedTestFonts[] = {{u8"CambriaMath", 1},
{u8"NSimSun", 1}, {u8"NSimSun", 1},
{u8"calibri-bolditalic", 0}}; {u8"calibri-bolditalic", 0}};
constexpr base::TimeDelta kTestingTimeout = base::TimeDelta::FromSeconds(10);
class DWriteFontLookupTableBuilderTest : public testing::Test { class DWriteFontLookupTableBuilderTest : public testing::Test {
public: public:
DWriteFontLookupTableBuilderTest() DWriteFontLookupTableBuilderTest()
...@@ -95,7 +97,8 @@ TEST_F(DWriteFontLookupTableBuilderTest, TestFindUniqueFontDirect) { ...@@ -95,7 +97,8 @@ TEST_F(DWriteFontLookupTableBuilderTest, TestFindUniqueFontDirect) {
} }
TEST_P(DWriteFontLookupTableBuilderTimeoutTest, TestTimeout) { TEST_P(DWriteFontLookupTableBuilderTimeoutTest, TestTimeout) {
font_lookup_table_builder_->SetSlowDownIndexingForTesting(GetParam()); font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout(
GetParam(), kTestingTimeout);
font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
font_lookup_table_builder_->EnsureFontUniqueNameTable(); font_lookup_table_builder_->EnsureFontUniqueNameTable();
base::ReadOnlySharedMemoryRegion font_table_memory = base::ReadOnlySharedMemoryRegion font_table_memory =
...@@ -119,8 +122,9 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -119,8 +122,9 @@ INSTANTIATE_TEST_SUITE_P(
DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask)); DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask));
TEST_F(DWriteFontLookupTableBuilderTest, TestReadyEarly) { TEST_F(DWriteFontLookupTableBuilderTest, TestReadyEarly) {
font_lookup_table_builder_->SetSlowDownIndexingForTesting( font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout(
DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask); DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask,
kTestingTimeout);
font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded();
ASSERT_FALSE(font_lookup_table_builder_->FontUniqueNameTableReady()); ASSERT_FALSE(font_lookup_table_builder_->FontUniqueNameTableReady());
font_lookup_table_builder_->ResumeFromHangForTesting(); font_lookup_table_builder_->ResumeFromHangForTesting();
......
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