Commit 3b4d46e3 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[blink] Use scheduler for script streaming

Add a new feature flag, ScheduledScriptStreaming, which makes the script
streamer use the task scheduler for streaming tasks, rather than using a
dedicated ScriptStreamerThread.

Bug: chromium:865098
Bug: chromium:866868
Change-Id: I05ca411d8d5187c4b5180011ebce2a603e3944fe
Reviewed-on: https://chromium-review.googlesource.com/1145386
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577543}
parent 1219b571
......@@ -406,6 +406,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableWorkStealingInScriptRunner(
base::FeatureList::IsEnabled(features::kWorkStealingInScriptRunner));
WebRuntimeFeatures::EnableScheduledScriptStreaming(
base::FeatureList::IsEnabled(features::kScheduledScriptStreaming));
WebRuntimeFeatures::EnableFeatureFromString(
"FeaturePolicyForPermissions",
base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions));
......
......@@ -590,6 +590,10 @@ const base::Feature kWipeCorruptV2IDBDatabases{
const base::Feature kWorkStealingInScriptRunner{
"WorkStealingInScriptRunner", base::FEATURE_DISABLED_BY_DEFAULT};
// Enabled scheduler use for script streaming.
const base::Feature kScheduledScriptStreaming{
"ScheduledScriptStreaming", base::FEATURE_DISABLED_BY_DEFAULT};
#if defined(OS_ANDROID)
// Autofill Accessibility in Android.
// crbug.com/627860
......
......@@ -135,6 +135,7 @@ CONTENT_EXPORT extern const base::Feature kWebXrHitTest;
CONTENT_EXPORT extern const base::Feature kWebXrOrientationSensorDevice;
CONTENT_EXPORT extern const base::Feature kWipeCorruptV2IDBDatabases;
CONTENT_EXPORT extern const base::Feature kWorkStealingInScriptRunner;
CONTENT_EXPORT extern const base::Feature kScheduledScriptStreaming;
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;
......
......@@ -191,6 +191,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableV8ContextSnapshot(bool);
BLINK_PLATFORM_EXPORT static void EnableAutomationControlled(bool);
BLINK_PLATFORM_EXPORT static void EnableWorkStealingInScriptRunner(bool);
BLINK_PLATFORM_EXPORT static void EnableScheduledScriptStreaming(bool);
BLINK_PLATFORM_EXPORT static void EnableStopInBackground(bool);
BLINK_PLATFORM_EXPORT static void EnableStopNonTimersInBackground(bool);
BLINK_PLATFORM_EXPORT static void EnablePWAFullCodeCache(bool);
......
......@@ -13,12 +13,15 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/script/classic_pending_script.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
......@@ -392,6 +395,19 @@ void ScriptStreamer::SuppressStreaming() {
streaming_suppressed_ = true;
}
static void RunScriptStreamingTask(
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
ScriptStreamer* streamer) {
TRACE_EVENT1(
"v8,devtools.timeline", "v8.parseOnBackground", "data",
InspectorParseScriptEvent::Data(streamer->ScriptResourceIdentifier(),
streamer->ScriptURLString()));
// Running the task can and will block: SourceStream::GetSomeData will get
// called and it will block and wait for data from the network.
task->Run();
streamer->StreamingCompleteOnBackgroundThread();
}
void ScriptStreamer::NotifyAppendData(ScriptResource* resource) {
DCHECK(IsMainThread());
if (streaming_suppressed_)
......@@ -436,11 +452,12 @@ void ScriptStreamer::NotifyAppendData(ScriptResource* resource) {
}
}
if (ScriptStreamerThread::Shared()->IsRunningTask()) {
// At the moment we only have one thread for running the tasks. A
// new task shouldn't be queued before the running task completes,
// because the running task can block and wait for data from the
// network.
if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled() &&
ScriptStreamerThread::Shared()->IsRunningTask()) {
// If scheduled script streaming is disabled, we only have one thread for
// running the tasks. A new task shouldn't be queued before the running
// task completes, because the running task can block and wait for data
// from the network.
SuppressStreaming();
RecordNotStreamingReasonHistogram(script_type_, kThreadBusy);
RecordStartedStreamingHistogram(script_type_, 0);
......@@ -476,10 +493,24 @@ void ScriptStreamer::NotifyAppendData(ScriptResource* resource) {
return;
}
ScriptStreamerThread::Shared()->PostTask(
CrossThreadBind(&ScriptStreamerThread::RunScriptStreamingTask,
WTF::Passed(std::move(script_streaming_task)),
WrapCrossThreadPersistent(this)));
if (RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
// Script streaming tasks are high priority, as they can block the
// parser, and they can (and probably will) block during their own
// execution as they wait for more input.
//
// TODO(leszeks): Decrease the priority of these tasks where possible.
BackgroundScheduler::PostOnBackgroundThreadWithTraits(
FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
CrossThreadBind(RunScriptStreamingTask,
WTF::Passed(std::move(script_streaming_task)),
WrapCrossThreadPersistent(this)));
} else {
ScriptStreamerThread::Shared()->PostTask(
CrossThreadBind(&ScriptStreamerThread::RunScriptStreamingTask,
WTF::Passed(std::move(script_streaming_task)),
WrapCrossThreadPersistent(this)));
}
RecordStartedStreamingHistogram(script_type_, 1);
}
if (stream_)
......
......@@ -108,8 +108,10 @@ class ScriptStreamingTest : public testing::Test {
}
void ProcessTasksUntilStreamingComplete() {
while (ScriptStreamerThread::Shared()->IsRunningTask()) {
test::RunPendingTasks();
if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
while (ScriptStreamerThread::Shared()->IsRunningTask()) {
test::RunPendingTasks();
}
}
// Once more, because the "streaming complete" notification might only
// now be in the task queue.
......
......@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
......@@ -22,19 +23,24 @@ static ScriptStreamerThread* g_shared_thread = nullptr;
static Mutex* g_mutex = nullptr;
void ScriptStreamerThread::Init() {
DCHECK(!g_shared_thread);
DCHECK(IsMainThread());
// This is called in the main thread before any tasks are created, so no
// locking is needed.
g_mutex = new Mutex();
g_shared_thread = new ScriptStreamerThread();
// Only enabled when ScheduledScriptStreaming is disabled.
if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
DCHECK(!g_shared_thread);
DCHECK(IsMainThread());
// This is called in the main thread before any tasks are created, so no
// locking is needed.
g_mutex = new Mutex();
g_shared_thread = new ScriptStreamerThread();
}
}
ScriptStreamerThread* ScriptStreamerThread::Shared() {
DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
return g_shared_thread;
}
void ScriptStreamerThread::PostTask(CrossThreadClosure task) {
DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
DCHECK(IsMainThread());
MutexLocker locker(mutex_);
DCHECK(!running_task_);
......@@ -60,6 +66,7 @@ WebThread& ScriptStreamerThread::PlatformThread() {
void ScriptStreamerThread::RunScriptStreamingTask(
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
ScriptStreamer* streamer) {
DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
TRACE_EVENT1(
"v8,devtools.timeline", "v8.parseOnBackground", "data",
InspectorParseScriptEvent::Data(streamer->ScriptResourceIdentifier(),
......
......@@ -524,6 +524,10 @@ void WebRuntimeFeatures::EnableWorkStealingInScriptRunner(bool enable) {
RuntimeEnabledFeatures::SetWorkStealingInScriptRunnerEnabled(enable);
}
void WebRuntimeFeatures::EnableScheduledScriptStreaming(bool enable) {
RuntimeEnabledFeatures::SetScheduledScriptStreamingEnabled(enable);
}
void WebRuntimeFeatures::EnableStopInBackground(bool enable) {
RuntimeEnabledFeatures::SetStopInBackgroundEnabled(enable);
}
......
......@@ -1117,6 +1117,9 @@
{
name: "RTCUnifiedPlanByDefault",
},
{
name: "ScheduledScriptStreaming",
},
{
name: "ScriptedSpeech",
status: "stable",
......
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