Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: pkg/front_end/example/incremental_reload/compiler_with_invalidation.dart

Issue 2928483005: Add an incremental reloader example and a utility tool to trigger a reload by (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// A wrapper on top of the [IncrementalKernelGenerator] that tracks
6 /// file modifications between subsequent compilation requests and only
7 /// invalidates those files that appear to be modified.
8 library front_end.example.incremental_reload.compiler_with_invalidation;
9
10 import 'dart:io';
11 import 'dart:async';
12 import 'dart:convert' show JSON;
13
14 import 'package:front_end/compiler_options.dart';
15 import 'package:front_end/incremental_kernel_generator.dart';
16 import 'package:front_end/src/incremental/file_byte_store.dart';
17 import 'package:front_end/src/incremental/byte_store.dart';
18 import 'package:kernel/ast.dart';
19 import 'package:kernel/binary/limited_ast_to_binary.dart';
20
21 /// Create an instance of an [IncrementalCompiler] to compile a program whose
22 /// main entry point file is [entry]. This uses some default options
23 /// for the location of the sdk and temporary folder to save intermediate
24 /// results.
25 // TODO(sigmund): make this example work outside of the SDK repo.
26 Future<IncrementalCompiler> createIncrementalCompiler(String entry,
27 {bool persistent: true}) {
28 var entryUri = Uri.base.resolve(entry);
29 var dartVm = Uri.base.resolve(Platform.resolvedExecutable);
30 var sdkRoot = dartVm.resolve("patched_sdk/");
31 var options = new CompilerOptions()
32 ..sdkRoot = sdkRoot
33 ..packagesFileUri = Uri.base.resolve('.packages')
34 ..strongMode = false
35 ..dartLibraries = loadDartLibraries(sdkRoot)
36 ..byteStore = persistent
37 ? new FileByteStore('/tmp/ikg_cache')
scheglov 2017/06/07 01:04:42 This will not work on Windows.
Siggi Cherem (dart-lang) 2017/06/07 20:17:11 Done.
38 : new MemoryByteStore();
39 return IncrementalCompiler.create(options, entryUri);
40 }
41
42 /// Reads the `libraries.json` file for an SDK to provide the location of the
43 /// SDK files.
44 // TODO(sigmund): this should be handled by package:front_end internally.
45 Map<String, Uri> loadDartLibraries(Uri sdkRoot) {
46 var libraries = sdkRoot.resolve('lib/libraries.json');
47 var map =
48 JSON.decode(new File.fromUri(libraries).readAsStringSync())['libraries'];
49 var dartLibraries = <String, Uri>{};
50 map.forEach((k, v) => dartLibraries[k] = libraries.resolve(v));
51 return dartLibraries;
52 }
53
54 /// An incremental compiler that monitors file modifications on disk and
55 /// invalidates only files that have been modified since the previous time the
56 /// compiler was invoked.
57 class IncrementalCompiler {
58 /// Underlying incremental compiler implementation.
59 IncrementalKernelGenerator _generator;
60
61 /// Last modification for each tracked input file.
62 Map<Uri, DateTime> lastModified = {};
63
64 /// Create an instance of [IncrementalCompiler].
65 static Future<IncrementalCompiler> create(
66 CompilerOptions options, Uri entryUri) async {
67 return new IncrementalCompiler._internal(
68 await IncrementalKernelGenerator.newInstance(options, entryUri));
69 }
70
71 IncrementalCompiler._internal(this._generator);
72
73 /// Callback for the [IncrementalKernelGenerator] to keep track of relevant
74 /// files.
75 Future _watch(Uri uri, bool used) {
76 if (used) {
77 if (lastModified[uri] == null) {
78 lastModified[uri] = new File.fromUri(uri).lastModifiedSync();
scheglov 2017/06/07 01:04:42 ??=
Siggi Cherem (dart-lang) 2017/06/07 20:17:11 Done.
79 }
80 } else {
81 lastModified.remove(uri);
82 }
83 return new Future.value(null);
84 }
85
86 /// How many files changed during the last call to [recompile].
87 int changed;
88
89 /// Time spent updating time-stamps from disk during the last call to
90 /// [recompile].
91 int invalidateTime;
92
93 /// Time actually spent compiling the code in the incremental compiler during
94 /// the last call to [recompile].
95 int compileTime;
96
97 /// Determine which files have been modified, and recompile the program
98 /// incrementally based on that information.
99 Future<Program> recompile() async {
100 changed = 0;
101 invalidateTime = 0;
102 compileTime = 0;
103
104 var invalidateTimer = new Stopwatch()..start();
105 for (var uri in lastModified.keys.toList()) {
106 var last = lastModified[uri];
107 var current = new File.fromUri(uri).lastModifiedSync();
108 if (last != current) {
109 lastModified[uri] = current;
110 _generator.invalidate(uri);
111 changed++;
112 }
113 }
114 invalidateTimer.stop();
115 invalidateTime = invalidateTimer.elapsedMilliseconds;
116 if (changed == 0 && lastModified.isNotEmpty) return null;
117
118 var compileTimer = new Stopwatch()..start();
119 var delta = await _generator.computeDelta(watch: _watch);
120 compileTimer.stop();
121 compileTime = compileTimer.elapsedMilliseconds;
122 var program = delta.newProgram;
123 return program;
124 }
125 }
126
127 /// The result of an incremental compile and metrics collected during the
128 /// the compilation.
129 class CompilationResult {
130 /// How many files were modified by the time we invoked the compiler again.
131 int changed = 0;
132
133 /// How many files are currently being tracked for modifications.
134 int totalFiles = 0;
135
136 /// How long it took to invalidate files that have been modified.
137 int invalidateTime = 0;
138
139 /// How long it took to build the incremental program.
140 int compileTime = 0;
141
142 /// How long it took to do the hot-reload in the VM.
143 int reloadTime = 0;
144
145 /// Whether we saw errors during compilation or reload.
146 bool errorSeen = false;
147
148 /// Error message when [errorSeen] is true.
149 String errorDetails;
150
151 /// The program that was generated by the incremental compiler.
152 Program program;
153 }
154
155 /// Request a recompile and possibly a reload, and gather timing metrics.
156 Future<CompilationResult> rebuild(
157 IncrementalCompiler compiler, Uri outputUri) async {
158 var result = new CompilationResult();
159 try {
160 var program = result.program = await compiler.recompile();
161 if (program != null && !program.libraries.isEmpty) {
162 // TODO(sigmund): the incremental generator should set the main method
163 // directly.
164 var mainLib = program.libraries.last;
165 program.mainMethod =
166 mainLib.procedures.firstWhere((p) => p.name.name == 'main');
167 var sink = new File.fromUri(outputUri).openWrite();
168
169 // TODO(sigmund): should the incremental generator always filter these
170 // libraries instead?
171 new LimitedBinaryPrinter(
172 sink, (library) => library.importUri.scheme != 'dart')
173 .writeProgramFile(program);
174 await sink.close();
175 }
176 } catch (e, t) {
177 result.errorDetails = 'compilation error: $e, $t';
178 result.errorSeen = true;
179 }
180
181 result.changed = compiler.changed;
182 result.totalFiles = compiler.lastModified.length;
183 result.invalidateTime = compiler.invalidateTime;
184 result.compileTime = compiler.compileTime;
185 result.reloadTime = 0;
186 return result;
187 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/example/incremental_reload/run.dart » ('j') | pkg/front_end/lib/src/incremental/file_state.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698