[ VM / CLI ] Run DartDev isolate from snapshot when possible

This change tries to run from dartdev.dart.snapshot and falls back to
running from dartdev.dill if incompatible VM flags are provided.

Fixes https://github.com/dart-lang/sdk/issues/43969

Performance results:

dart test.dart (no CLI isolate): 0.167s
dart run test (from snapshot):   0.208s
dart run test (from kernel):     0.326s

TEST=pkg/dartdev/test/load_from_dill_test.dart

Change-Id: I3195886b86676580ef2a0221f0284328964ef061
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178300
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Ben Konyi
2021-01-11 19:41:50 +00:00
committed by commit-bot@chromium.org
parent 9d1a307954
commit c42c76f590
6 changed files with 131 additions and 26 deletions
+29
View File
@@ -0,0 +1,29 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:test/test.dart';
import 'utils.dart';
void main() {
TestProject p;
tearDown(() => p?.dispose());
test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
() {
p = project(mainSrc: "void main() { print('Hello World'); }");
// The DartDev snapshot includes the --use-bare-instructions flag. If
// --no-use-bare-instructions is passed, the VM will fail to load the
// snapshot and should fall back to using the DartDev dill file.
ProcessResult result =
p.runSync(['--no-use-bare-instructions', 'run', p.relativeFilePath]);
expect(result.stdout, contains('Hello World'));
expect(result.stderr, isEmpty);
expect(result.exitCode, 0);
});
}
+12 -3
View File
@@ -57,13 +57,14 @@ bool DartDevIsolate::ShouldParseCommand(const char* script_uri) {
(strncmp(script_uri, "google3://", 10) != 0));
}
Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
Utils::CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(
const char* filename) {
// |dir_prefix| includes the last path seperator.
auto dir_prefix = EXEUtils::GetDirectoryPrefixFromExeName();
// First assume we're in dart-sdk/bin.
char* snapshot_path =
Utils::SCreate("%ssnapshots/dartdev.dill", dir_prefix.get());
Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
if (File::Exists(nullptr, snapshot_path)) {
return Utils::CreateCStringUniquePtr(snapshot_path);
}
@@ -71,7 +72,7 @@ Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
// If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
// directories. Try to use a snapshot from a previously built SDK.
snapshot_path = Utils::SCreate("%sdartdev.dill", dir_prefix.get());
snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
if (File::Exists(nullptr, snapshot_path)) {
return Utils::CreateCStringUniquePtr(snapshot_path);
}
@@ -79,6 +80,14 @@ Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
return Utils::CreateCStringUniquePtr(nullptr);
}
Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
return TryResolveArtifactPath("dartdev.dart.snapshot");
}
Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevKernelPath() {
return TryResolveArtifactPath("dartdev.dill");
}
void DartDevIsolate::DartDevRunner::Run(
Dart_IsolateGroupCreateCallback create_isolate,
char** packages_file,
+6 -2
View File
@@ -41,8 +41,10 @@ class DartDevIsolate {
static bool should_run_dart_dev() { return should_run_dart_dev_; }
// Attempts to find the DartDev snapshot. If the snapshot cannot be found,
// the VM will shutdown.
// Attempts to find the path of the DartDev kernel file.
static Utils::CStringUniquePtr TryResolveDartDevKernelPath();
// Attempts to find the path of the DartDev snapshot.
static Utils::CStringUniquePtr TryResolveDartDevSnapshotPath();
// Starts a DartDev instance in a new isolate and runs it to completion.
@@ -89,6 +91,8 @@ class DartDevIsolate {
};
private:
static Utils::CStringUniquePtr TryResolveArtifactPath(const char* filename);
static DartDevRunner runner_;
static bool should_run_dart_dev_;
+56 -20
View File
@@ -584,40 +584,76 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
int64_t start = Dart_TimelineGetMicros();
auto dartdev_path = DartDevIsolate::TryResolveDartDevSnapshotPath();
if (dartdev_path == nullptr) {
*error = Utils::StrDup("Unable to find DartDev snapshot");
return nullptr;
}
Dart_Isolate isolate = nullptr;
const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
const uint8_t* isolate_snapshot_instructions =
core_isolate_snapshot_instructions;
IsolateGroupData* isolate_group_data = nullptr;
IsolateData* isolate_data = nullptr;
auto isolate_group_data =
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
/*isolate_run_app_snapshot*/ false);
uint8_t* application_kernel_buffer = NULL;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
&application_kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(application_kernel_buffer,
application_kernel_buffer_size);
AppSnapshot* app_snapshot;
bool isolate_run_app_snapshot = true;
if (dartdev_path.get() != nullptr &&
(app_snapshot = Snapshot::TryReadAppSnapshot(dartdev_path.get())) !=
nullptr) {
const uint8_t* isolate_snapshot_data = NULL;
const uint8_t* isolate_snapshot_instructions = NULL;
const uint8_t* ignore_vm_snapshot_data;
const uint8_t* ignore_vm_snapshot_instructions;
app_snapshot->SetBuffers(
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
&isolate_snapshot_data, &isolate_snapshot_instructions);
isolate_group_data =
new IsolateGroupData(dartdev_path.get(), packages_config, app_snapshot,
isolate_run_app_snapshot);
isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
error);
}
auto isolate_data = new IsolateData(isolate_group_data);
Dart_Isolate isolate = nullptr;
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
error);
if (isolate == nullptr) {
isolate_run_app_snapshot = false;
dartdev_path = DartDevIsolate::TryResolveDartDevKernelPath();
// Clear error from app snapshot and retry from kernel.
free(*error);
*error = nullptr;
if (app_snapshot != nullptr) {
delete app_snapshot;
}
if (dartdev_path.get() != nullptr) {
isolate_group_data =
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
isolate_run_app_snapshot);
uint8_t* application_kernel_buffer = NULL;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
&application_kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(
application_kernel_buffer, application_kernel_buffer_size);
isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data,
isolate_data, error);
}
}
Dart_Isolate created_isolate = nullptr;
if (isolate == nullptr) {
Syslog::PrintErr("Failed to start the Dart CLI isolate\n");
delete isolate_data;
delete isolate_group_data;
return nullptr;
} else {
created_isolate = IsolateSetupHelper(
isolate, false, DART_DEV_ISOLATE_NAME, packages_config,
/*isolate_run_app_snapshot*/ false, flags, error, exit_code);
isolate_run_app_snapshot, flags, error, exit_code);
}
int64_t end = Dart_TimelineGetMicros();
Dart_TimelineEvent("CreateAndSetupDartDevIsolate", start, end,
+9
View File
@@ -48,6 +48,7 @@ declare_args() {
# ........dart2js.dart.snapshot
# ........dart2native.dart.snapshot (if not on ia32)
# ........dartanalyzer.dart.snapshot
# ........dartdev.dart.snapshot
# ........dartdev.dill
# ........dartdevc.dart.snapshot
# ........dartdoc.dart.snapshot
@@ -117,6 +118,10 @@ _platform_sdk_snapshots = [
"dartanalyzer",
"../utils/dartanalyzer:generate_dartanalyzer_snapshot",
],
[
"dartdev",
"../utils/dartdev:dartdev",
],
[
"dartdoc",
"../utils/dartdoc",
@@ -162,6 +167,10 @@ _full_sdk_snapshots = [
"dartanalyzer",
"../utils/dartanalyzer:generate_dartanalyzer_snapshot",
],
[
"dartdev",
"../utils/dartdev:generate_dartdev_snapshot",
],
[
"dartdevc",
"../utils/dartdevc",
+19 -1
View File
@@ -12,7 +12,10 @@ dartdev_files = exec_script("../../tools/list_dart_files.py",
"list lines")
group("dartdev") {
public_deps = [ ":copy_dartdev_kernel" ]
public_deps = [
":copy_dartdev_kernel",
":copy_dartdev_snapshot",
]
}
copy("copy_dartdev_kernel") {
@@ -30,3 +33,18 @@ application_snapshot("generate_dartdev_kernel") {
inputs = dartdev_files
output = "$root_gen_dir/dartdev.dill"
}
copy("copy_dartdev_snapshot") {
visibility = [ ":dartdev" ]
public_deps = [ ":generate_dartdev_snapshot" ]
sources = [ "$root_gen_dir/dartdev.dart.snapshot" ]
outputs = [ "$root_out_dir/dartdev.dart.snapshot" ]
}
application_snapshot("generate_dartdev_snapshot") {
main_dart = "../../pkg/dartdev/bin/dartdev.dart"
training_args = [ "--help" ]
deps = [ "../dds:dds" ]
inputs = dartdev_files
output = "$root_gen_dir/dartdev.dart.snapshot"
}