mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 16:04:53 +00:00
[dart2js] Add dart:_dart2js_runtime_metrics library and package
The internal dart:_dart2js_runtime_metrics library is accessed via package:dart2js_runtime_metrics. There is currently one API: startupMetrics. On non-dart2js configurations the API is stubbed for ease-of-use. Change-Id: I80c56a83fd166ec19c3846fb6937cf0440ed2c6b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208563 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
3fb85e4342
commit
23b50dfa7d
|
@ -11,7 +11,7 @@
|
|||
"constraint, update this by running tools/generate_package_config.dart."
|
||||
],
|
||||
"configVersion": 2,
|
||||
"generated": "2021-07-27T19:27:52.638315",
|
||||
"generated": "2021-07-30T20:37:49.663747",
|
||||
"generator": "tools/generate_package_config.dart",
|
||||
"packages": [
|
||||
{
|
||||
|
@ -204,6 +204,12 @@
|
|||
"packageUri": "lib/",
|
||||
"languageVersion": "2.3"
|
||||
},
|
||||
{
|
||||
"name": "dart2js_runtime_metrics",
|
||||
"rootUri": "../pkg/dart2js_runtime_metrics",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.14"
|
||||
},
|
||||
{
|
||||
"name": "dart2js_tools",
|
||||
"rootUri": "../pkg/dart2js_tools",
|
||||
|
|
|
@ -30,6 +30,7 @@ convert:third_party/pkg/convert/lib
|
|||
crypto:third_party/pkg/crypto/lib
|
||||
csslib:third_party/pkg/csslib/lib
|
||||
dart2js_info:third_party/pkg/dart2js_info/lib
|
||||
dart2js_runtime_metrics:pkg/dart2js_runtime_metrics/lib
|
||||
dart2js_tools:pkg/dart2js_tools/lib
|
||||
dart2native:pkg/dart2native/lib
|
||||
dart_internal:pkg/dart_internal/lib
|
||||
|
|
|
@ -388,6 +388,9 @@ abstract class CommonElements {
|
|||
/// Holds the method "requiresPreamble" in _js_helper.
|
||||
FunctionEntity get requiresPreambleMarker;
|
||||
|
||||
/// Holds the method "_rawStartupMetrics" in _js_helper.
|
||||
FunctionEntity get rawStartupMetrics;
|
||||
|
||||
FunctionEntity get loadLibraryWrapper;
|
||||
|
||||
FunctionEntity get loadDeferredLibrary;
|
||||
|
@ -1665,6 +1668,11 @@ class CommonElementsImpl
|
|||
FunctionEntity get requiresPreambleMarker =>
|
||||
_requiresPreambleMarker ??= _findHelperFunction('requiresPreamble');
|
||||
|
||||
FunctionEntity _rawStartupMetrics;
|
||||
@override
|
||||
FunctionEntity get rawStartupMetrics =>
|
||||
_rawStartupMetrics ??= _findHelperFunction('rawStartupMetrics');
|
||||
|
||||
@override
|
||||
FunctionEntity get loadLibraryWrapper =>
|
||||
_findHelperFunction("_loadLibraryWrapper");
|
||||
|
|
|
@ -51,6 +51,9 @@ abstract class BackendUsage {
|
|||
/// `true` if 'dart:mirrors' features are used.
|
||||
bool get isMirrorsUsed;
|
||||
|
||||
/// `true` if startup timestamps are used.
|
||||
bool get requiresStartupMetrics;
|
||||
|
||||
/// `true` if `noSuchMethod` is used.
|
||||
bool get isNoSuchMethodUsed;
|
||||
|
||||
|
@ -120,6 +123,9 @@ class BackendUsageBuilderImpl implements BackendUsageBuilder {
|
|||
/// `true` if a core-library function requires the preamble file to function.
|
||||
bool requiresPreamble = false;
|
||||
|
||||
/// `true` if a core-library function accesses startup timestamps.
|
||||
bool requiresStartupMetrics = false;
|
||||
|
||||
@override
|
||||
bool isFunctionApplyUsed = false;
|
||||
|
||||
|
@ -242,6 +248,8 @@ class BackendUsageBuilderImpl implements BackendUsageBuilder {
|
|||
isFunctionApplyUsed = true;
|
||||
} else if (member.library == _commonElements.mirrorsLibrary) {
|
||||
isMirrorsUsed = true;
|
||||
} else if (member == _commonElements.rawStartupMetrics) {
|
||||
requiresStartupMetrics = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +283,7 @@ class BackendUsageBuilderImpl implements BackendUsageBuilder {
|
|||
|
||||
@override
|
||||
BackendUsage close() {
|
||||
return new BackendUsageImpl(
|
||||
return BackendUsageImpl(
|
||||
globalFunctionDependencies: _globalFunctionDependencies,
|
||||
globalClassDependencies: _globalClassDependencies,
|
||||
helperFunctionsUsed: _helperFunctionsUsed,
|
||||
|
@ -283,6 +291,7 @@ class BackendUsageBuilderImpl implements BackendUsageBuilder {
|
|||
needToInitializeIsolateAffinityTag: _needToInitializeIsolateAffinityTag,
|
||||
needToInitializeDispatchProperty: _needToInitializeDispatchProperty,
|
||||
requiresPreamble: requiresPreamble,
|
||||
requiresStartupMetrics: requiresStartupMetrics,
|
||||
runtimeTypeUses: _runtimeTypeUses,
|
||||
isFunctionApplyUsed: isFunctionApplyUsed,
|
||||
isMirrorsUsed: isMirrorsUsed,
|
||||
|
@ -316,6 +325,9 @@ class BackendUsageImpl implements BackendUsage {
|
|||
@override
|
||||
final bool requiresPreamble;
|
||||
|
||||
@override
|
||||
final bool requiresStartupMetrics;
|
||||
|
||||
@override
|
||||
final bool isFunctionApplyUsed;
|
||||
|
||||
|
@ -336,6 +348,7 @@ class BackendUsageImpl implements BackendUsage {
|
|||
this.needToInitializeIsolateAffinityTag,
|
||||
this.needToInitializeDispatchProperty,
|
||||
this.requiresPreamble,
|
||||
this.requiresStartupMetrics,
|
||||
Set<RuntimeTypeUse> runtimeTypeUses,
|
||||
this.isFunctionApplyUsed,
|
||||
this.isMirrorsUsed,
|
||||
|
@ -364,12 +377,13 @@ class BackendUsageImpl implements BackendUsage {
|
|||
bool needToInitializeIsolateAffinityTag = source.readBool();
|
||||
bool needToInitializeDispatchProperty = source.readBool();
|
||||
bool requiresPreamble = source.readBool();
|
||||
bool requiresStartupMetrics = source.readBool();
|
||||
bool isFunctionApplyUsed = source.readBool();
|
||||
bool isMirrorsUsed = source.readBool();
|
||||
bool isNoSuchMethodUsed = source.readBool();
|
||||
bool isHtmlLoaded = source.readBool();
|
||||
source.end(tag);
|
||||
return new BackendUsageImpl(
|
||||
return BackendUsageImpl(
|
||||
globalFunctionDependencies: globalFunctionDependencies,
|
||||
globalClassDependencies: globalClassDependencies,
|
||||
helperFunctionsUsed: helperFunctionsUsed,
|
||||
|
@ -378,6 +392,7 @@ class BackendUsageImpl implements BackendUsage {
|
|||
needToInitializeIsolateAffinityTag: needToInitializeIsolateAffinityTag,
|
||||
needToInitializeDispatchProperty: needToInitializeDispatchProperty,
|
||||
requiresPreamble: requiresPreamble,
|
||||
requiresStartupMetrics: requiresStartupMetrics,
|
||||
isFunctionApplyUsed: isFunctionApplyUsed,
|
||||
isMirrorsUsed: isMirrorsUsed,
|
||||
isNoSuchMethodUsed: isNoSuchMethodUsed,
|
||||
|
@ -399,6 +414,7 @@ class BackendUsageImpl implements BackendUsage {
|
|||
sink.writeBool(needToInitializeIsolateAffinityTag);
|
||||
sink.writeBool(needToInitializeDispatchProperty);
|
||||
sink.writeBool(requiresPreamble);
|
||||
sink.writeBool(requiresStartupMetrics);
|
||||
sink.writeBool(isFunctionApplyUsed);
|
||||
sink.writeBool(isMirrorsUsed);
|
||||
sink.writeBool(isNoSuchMethodUsed);
|
||||
|
|
|
@ -14,8 +14,8 @@ import '../common_elements.dart';
|
|||
import 'code_emitter_task.dart' show Emitter;
|
||||
|
||||
class MainCallStubGenerator {
|
||||
static jsAst.Statement generateInvokeMain(
|
||||
CommonElements commonElements, Emitter emitter, FunctionEntity main) {
|
||||
static jsAst.Statement generateInvokeMain(CommonElements commonElements,
|
||||
Emitter emitter, FunctionEntity main, bool requiresStartupMetrics) {
|
||||
jsAst.Expression mainAccess = emitter.staticFunctionAccess(main);
|
||||
jsAst.Expression currentScriptAccess =
|
||||
emitter.generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT);
|
||||
|
@ -90,6 +90,10 @@ class MainCallStubGenerator {
|
|||
}
|
||||
})(function(currentScript) {
|
||||
#currentScript = currentScript;
|
||||
|
||||
if (#startupMetrics) {
|
||||
init.#startupMetricsEmbeddedGlobal.add('callMainMs');
|
||||
}
|
||||
var callMain = #mainCallClosure;
|
||||
if (typeof dartMainRunner === "function") {
|
||||
dartMainRunner(callMain, []);
|
||||
|
@ -98,7 +102,9 @@ class MainCallStubGenerator {
|
|||
}
|
||||
})''', {
|
||||
'currentScript': currentScriptAccess,
|
||||
'mainCallClosure': mainCallClosure
|
||||
'mainCallClosure': mainCallClosure,
|
||||
'startupMetrics': requiresStartupMetrics,
|
||||
'startupMetricsEmbeddedGlobal': embeddedNames.STARTUP_METRICS,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -294,8 +294,8 @@ class ProgramBuilder {
|
|||
}
|
||||
|
||||
js.Statement _buildInvokeMain() {
|
||||
return MainCallStubGenerator.generateInvokeMain(
|
||||
_commonElements, _task.emitter, _mainFunction);
|
||||
return MainCallStubGenerator.generateInvokeMain(_commonElements,
|
||||
_task.emitter, _mainFunction, _backendUsage.requiresStartupMetrics);
|
||||
}
|
||||
|
||||
DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) {
|
||||
|
|
|
@ -35,6 +35,15 @@ part of dart2js.js_emitter.startup_emitter.model_emitter;
|
|||
// reducing their size.
|
||||
const String _mainBoilerplate = '''
|
||||
(function dartProgram() {
|
||||
|
||||
if (#startupMetrics) {
|
||||
// Stash the metrics on the main unit IIFE.
|
||||
// TODO(sra): When the JavaScript local renamer is more intelligent, we can
|
||||
// simply use a local variable.
|
||||
(dartProgram.$STARTUP_METRICS = ${ModelEmitter.startupMetricsGlobal})
|
||||
.add("dartProgramMs");
|
||||
}
|
||||
|
||||
// Copies the own properties from [from] to [to].
|
||||
function copyProperties(from, to) {
|
||||
var keys = Object.keys(from);
|
||||
|
@ -469,7 +478,7 @@ convertToFastObject(#staticState);
|
|||
|
||||
// Invokes main (making sure that it records the 'current-script' value).
|
||||
#invokeMain;
|
||||
})()
|
||||
})();
|
||||
''';
|
||||
|
||||
/// An expression that returns `true` if `__proto__` can be assigned to stitch
|
||||
|
@ -720,6 +729,7 @@ class FragmentEmitter {
|
|||
'staticStateDeclaration': DeferredHolderParameter(),
|
||||
'staticState': DeferredHolderParameter(),
|
||||
'holders': holderDeclaration,
|
||||
'startupMetrics': _closedWorld.backendUsage.requiresStartupMetrics,
|
||||
|
||||
// Tearoff parameters:
|
||||
'tpContainer': js.string(TearOffParametersPropertyNames.container),
|
||||
|
@ -1847,6 +1857,12 @@ class FragmentEmitter {
|
|||
r' : "$ti"')
|
||||
: js.js(r'Symbol("$ti")')));
|
||||
|
||||
if (_closedWorld.backendUsage.requiresStartupMetrics) {
|
||||
// Copy the metrics object that was stored on the main unit IIFE.
|
||||
globals.add(js.Property(
|
||||
js.string(STARTUP_METRICS), js.js('dartProgram.$STARTUP_METRICS')));
|
||||
}
|
||||
|
||||
js.ObjectInitializer globalsObject =
|
||||
js.ObjectInitializer(globals, isOneLiner: false);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import 'package:js_runtime/shared/embedded_names.dart'
|
|||
NATIVE_SUPERCLASS_TAG_NAME,
|
||||
RTI_UNIVERSE,
|
||||
RtiUniverseFieldNames,
|
||||
STARTUP_METRICS,
|
||||
TearOffParametersPropertyNames,
|
||||
TYPE_TO_INTERCEPTOR_MAP,
|
||||
TYPES;
|
||||
|
@ -136,6 +137,8 @@ class ModelEmitter {
|
|||
static const String deferredInitializersGlobal =
|
||||
r"$__dart_deferred_initializers__";
|
||||
|
||||
static const String startupMetricsGlobal = r'$__dart_startupMetrics';
|
||||
|
||||
static const String partExtension = "part";
|
||||
static const String deferredExtension = "part.js";
|
||||
|
||||
|
@ -372,6 +375,32 @@ class ModelEmitter {
|
|||
{'deferredInitializers': deferredInitializersGlobal});
|
||||
}
|
||||
|
||||
js.Statement buildStartupMetrics() {
|
||||
// We want the code that initializes the startup metrics to execute as early
|
||||
// as possible, so it is placed ahead of the main program IIFE instead of,
|
||||
// e.g. as a parameter of the IIFE. It is OK to use a top-level variable,
|
||||
// since the IIFE immediately reads the variable.
|
||||
return js.js.statement('''
|
||||
var ${startupMetricsGlobal} =
|
||||
(function(){
|
||||
// The timestamp metrics use `performance.now()`. We feature-detect and
|
||||
// fall back on `Date.now()` for JavaScript run in a non-browser evironment.
|
||||
var _performance =
|
||||
(typeof performance == "object" &&
|
||||
performance != null &&
|
||||
typeof performance.now == "function")
|
||||
? performance
|
||||
: Date;
|
||||
var metrics = {
|
||||
a: [],
|
||||
now: function() { return _performance.now() },
|
||||
add: function(name) { this.a.push(name, this.now()); }
|
||||
};
|
||||
metrics.add('firstMs');
|
||||
return metrics;
|
||||
})();''');
|
||||
}
|
||||
|
||||
// Writes the given [fragment]'s [code] into a file.
|
||||
//
|
||||
// Updates the shared [outputBuffers] field with the output.
|
||||
|
@ -395,6 +424,8 @@ class ModelEmitter {
|
|||
buildGeneratedBy(),
|
||||
js.Comment(HOOKS_API_USAGE),
|
||||
if (isSplit) buildDeferredInitializerGlobal(),
|
||||
if (_closedWorld.backendUsage.requiresStartupMetrics)
|
||||
buildStartupMetrics(),
|
||||
code
|
||||
]);
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ class JsClosedWorldBuilder {
|
|||
map.toBackendType(runtimeTypeUse.argumentType));
|
||||
}).toSet();
|
||||
|
||||
return new BackendUsageImpl(
|
||||
return BackendUsageImpl(
|
||||
globalFunctionDependencies: globalFunctionDependencies,
|
||||
globalClassDependencies: globalClassDependencies,
|
||||
helperFunctionsUsed: helperFunctionsUsed,
|
||||
|
@ -266,6 +266,7 @@ class JsClosedWorldBuilder {
|
|||
needToInitializeDispatchProperty:
|
||||
backendUsage.needToInitializeDispatchProperty,
|
||||
requiresPreamble: backendUsage.requiresPreamble,
|
||||
requiresStartupMetrics: backendUsage.requiresStartupMetrics,
|
||||
runtimeTypeUses: runtimeTypeUses,
|
||||
isFunctionApplyUsed: backendUsage.isFunctionApplyUsed,
|
||||
isMirrorsUsed: backendUsage.isMirrorsUsed,
|
||||
|
|
|
@ -131,7 +131,9 @@ class Dart2jsTarget extends Target {
|
|||
@override
|
||||
bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
|
||||
super.allowPlatformPrivateLibraryAccess(importer, imported) ||
|
||||
maybeEnableNative(importer);
|
||||
maybeEnableNative(importer) ||
|
||||
(importer.scheme == 'package' &&
|
||||
importer.path.startsWith('dart2js_runtime_metrics/'));
|
||||
|
||||
@override
|
||||
bool enableNative(Uri uri) => maybeEnableNative(uri);
|
||||
|
@ -235,6 +237,7 @@ class Dart2jsTarget extends Target {
|
|||
// compile-platform should just specify which libraries to compile instead.
|
||||
const _requiredLibraries = const <String, List<String>>{
|
||||
'dart2js': const <String>[
|
||||
'dart:_dart2js_runtime_metrics',
|
||||
'dart:_foreign_helper',
|
||||
'dart:_interceptors',
|
||||
'dart:_internal',
|
||||
|
@ -258,6 +261,7 @@ const _requiredLibraries = const <String, List<String>>{
|
|||
'dart:web_sql',
|
||||
],
|
||||
'dart2js_server': const <String>[
|
||||
'dart:_dart2js_runtime_metrics',
|
||||
'dart:_foreign_helper',
|
||||
'dart:_interceptors',
|
||||
'dart:_internal',
|
||||
|
|
3
pkg/dart2js_runtime_metrics/CHANGELOG.md
Normal file
3
pkg/dart2js_runtime_metrics/CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## 0.1.0
|
||||
|
||||
- Initial version.
|
27
pkg/dart2js_runtime_metrics/LICENSE
Normal file
27
pkg/dart2js_runtime_metrics/LICENSE
Normal file
|
@ -0,0 +1,27 @@
|
|||
Copyright 2021, the Dart project authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
13
pkg/dart2js_runtime_metrics/README.md
Normal file
13
pkg/dart2js_runtime_metrics/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
☠☠ **Warning: This package is experimental and may be removed in a future
|
||||
version of Dart.** ☠☠
|
||||
|
||||
`dart2js` can generate extra code to measure certain activities.
|
||||
This library provides access to the measurements at runtime.
|
||||
|
||||
An application might make timings and other measurements and report them back to
|
||||
a server in order to collect information on how the application is working in
|
||||
production. The APIs in this library provide access to measurements that require
|
||||
help from dart2js. For example, `startupMetrics` accesses measurements of
|
||||
activities that happen as the program is loaded, before `main()`.
|
||||
|
||||
The APIs are stubbed so that dummy values are returned on the VM and dartdevc.
|
5
pkg/dart2js_runtime_metrics/analysis_options.yaml
Normal file
5
pkg/dart2js_runtime_metrics/analysis_options.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
analyzer:
|
||||
errors:
|
||||
import_internal_library: ignore
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -0,0 +1,5 @@
|
|||
// 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.
|
||||
|
||||
export 'dart:_dart2js_runtime_metrics' show startupMetrics;
|
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
/// A collection of metrics for events that happen before `main()` is entered.
|
||||
///
|
||||
/// The contents of the map depend on the platform. The map values are simple
|
||||
/// objects (strings, numbers, Booleans). There is always an entry for the key
|
||||
/// `'runtime'` with a [String] value.
|
||||
Map<String, Object> get startupMetrics {
|
||||
return {'runtime': 'dartdevc'};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
/// A collection of metrics for events that happen before `main()` is entered.
|
||||
///
|
||||
/// The contents of the map depend on the platform. The map values are simple
|
||||
/// objects (strings, numbers, Booleans). There is always an entry for the key
|
||||
/// `'runtime'` with a [String] value.
|
||||
Map<String, Object> get startupMetrics {
|
||||
return {'runtime': 'unknown'};
|
||||
}
|
12
pkg/dart2js_runtime_metrics/lib/_startup_metrics_vm.dart
Normal file
12
pkg/dart2js_runtime_metrics/lib/_startup_metrics_vm.dart
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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.
|
||||
|
||||
/// A collection of metrics for events that happen before `main()` is entered.
|
||||
///
|
||||
/// The contents of the map depend on the platform. The map values are simple
|
||||
/// objects (strings, numbers, Booleans). There is always an entry for the key
|
||||
/// `'runtime'` with a [String] value.
|
||||
Map<String, Object> get startupMetrics {
|
||||
return {'runtime': 'vm'};
|
||||
}
|
8
pkg/dart2js_runtime_metrics/lib/startup_metrics.dart
Normal file
8
pkg/dart2js_runtime_metrics/lib/startup_metrics.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
export '_startup_metrics_unknown.dart'
|
||||
if (dart.library._dart2js_runtime_metrics) '_startup_metrics_dart2js.dart'
|
||||
if (dart.library.ffi) '_startup_metrics_vm.dart'
|
||||
if (dart.library.js) '_startup_metrics_dartdevc.dart';
|
18
pkg/dart2js_runtime_metrics/pubspec.yaml
Normal file
18
pkg/dart2js_runtime_metrics/pubspec.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
name: dart2js_runtime_metrics
|
||||
# This package is not intended for consumption on pub.dev. DO NOT publish.
|
||||
publish_to: none
|
||||
version: 0.1.0
|
||||
repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart2js_runtime_metrics
|
||||
description: >-
|
||||
`dart2js` can generate extra code to measure certain activities.
|
||||
This library provides access to the measurements at runtime.
|
||||
|
||||
environment:
|
||||
# Restrict the upper bound so that we can remove support for this in
|
||||
# a later version of the SDK without it being a breaking change.
|
||||
sdk: ">=2.14.0 <2.15.0"
|
||||
|
||||
dev_dependencies:
|
||||
# Unpublished packages that can be used via path dependency
|
||||
expect:
|
||||
path: ../expect
|
51
pkg/dart2js_runtime_metrics/test/startup_metrics_test.dart
Normal file
51
pkg/dart2js_runtime_metrics/test/startup_metrics_test.dart
Normal file
|
@ -0,0 +1,51 @@
|
|||
// 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 'package:dart2js_runtime_metrics/startup_metrics.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
void main() {
|
||||
Map<String, Object> metrics = startupMetrics;
|
||||
|
||||
print('metrics: $metrics');
|
||||
|
||||
String expectedRuntime;
|
||||
if (1.0 is! int) {
|
||||
expectedRuntime = 'vm';
|
||||
} else if (ClassWithLongName().toString().contains('minified:')) {
|
||||
// dart2js minified: "Instance of 'minified:xy'".
|
||||
expectedRuntime = 'dart2js';
|
||||
} else if ('$main' == "Closure 'main'") {
|
||||
// dart2js non-minified.
|
||||
expectedRuntime = 'dart2js';
|
||||
} else if ('$main'.startsWith('Closure: () => void from: function main()')) {
|
||||
expectedRuntime = 'dartdevc';
|
||||
} else {
|
||||
throw 'Cannot feature-test current runtime:'
|
||||
'\nmetrics = $metrics\n main = $main';
|
||||
}
|
||||
|
||||
Expect.isTrue(metrics.containsKey('runtime'), "Has 'runtime' key: $metrics");
|
||||
Expect.equals(expectedRuntime, metrics['runtime'],
|
||||
"Expected 'runtime: $expectedRuntime': $metrics");
|
||||
|
||||
if (expectedRuntime == 'dart2js') {
|
||||
Expect.isTrue(metrics.containsKey('callMainMs'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedRuntime == 'dartdevc') {
|
||||
Expect.equals(1, metrics.length);
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedRuntime == 'vm') {
|
||||
Expect.equals(1, metrics.length);
|
||||
return;
|
||||
}
|
||||
|
||||
throw 'Should not get here.';
|
||||
}
|
||||
|
||||
class ClassWithLongName {}
|
|
@ -1866,6 +1866,8 @@ met
|
|||
metadata
|
||||
method
|
||||
methods
|
||||
metric
|
||||
metrics
|
||||
microseconds
|
||||
microtask
|
||||
mid
|
||||
|
|
|
@ -179,6 +179,9 @@ const DEFERRED_INITIALIZED = 'deferredInitialized';
|
|||
/// This embedded global is used for --experiment-new-rti.
|
||||
const RTI_UNIVERSE = 'typeUniverse';
|
||||
|
||||
/// An embedded global used to collect and access startup metrics.
|
||||
const STARTUP_METRICS = 'sm';
|
||||
|
||||
/// Names that are supported by [JS_GET_NAME].
|
||||
// TODO(herhut): Make entries lower case (as in fields) and find a better name.
|
||||
enum JsGetName {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// 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.
|
||||
|
||||
library dart2js_runtime_metrics;
|
||||
|
||||
import 'dart:_js_helper' show fillLiteralMap, rawStartupMetrics;
|
||||
|
||||
/// A collection of metrics for events that happen before `main()` is entered.
|
||||
///
|
||||
/// The contents of the map depend on the platform. The map values are simple
|
||||
/// objects (strings, numbers, Booleans). There is always an entry for the key
|
||||
/// `'runtime'` with a [String] value.
|
||||
///
|
||||
/// This implementation for dart2js has the content (subject to change):
|
||||
///
|
||||
/// - `runtime`: `'dart2js'`
|
||||
///
|
||||
/// - `firstMs`: first performance.now() reading in the main.dart.js file.
|
||||
///
|
||||
/// - `dartMainProgramMs`: performance.now() immediately inside the function
|
||||
/// wrapping all the Dart code
|
||||
///
|
||||
/// - `callMainMs`: performance.now() just before calling main()
|
||||
///
|
||||
/// The injected code uses `Date.now()` if `performance.now()` is not defined.
|
||||
Map<String, Object> get startupMetrics {
|
||||
final Map<String, Object> result = {'runtime': 'dart2js'};
|
||||
final raw = rawStartupMetrics();
|
||||
fillLiteralMap(raw, result);
|
||||
return result;
|
||||
}
|
|
@ -21,6 +21,7 @@ import 'dart:_js_embedded_names'
|
|||
JsGetName,
|
||||
LEAF_TAGS,
|
||||
NATIVE_SUPERCLASS_TAG_NAME,
|
||||
STARTUP_METRICS,
|
||||
STATIC_FUNCTION_NAME_PROPERTY_NAME,
|
||||
TearOffParametersPropertyNames;
|
||||
|
||||
|
@ -3005,3 +3006,7 @@ void assertInteropArgs(List<Object?> args) {
|
|||
assert(args.every((arg) => arg is! Function || isJSFunction(arg)),
|
||||
'Dart function requires `allowInterop` to be passed to JavaScript.');
|
||||
}
|
||||
|
||||
Object? rawStartupMetrics() {
|
||||
return JS('JSArray', '#.a', JS_EMBEDDED_GLOBAL('', STARTUP_METRICS));
|
||||
}
|
||||
|
|
|
@ -179,6 +179,9 @@ const DEFERRED_INITIALIZED = 'deferredInitialized';
|
|||
/// This embedded global is used for --experiment-new-rti.
|
||||
const RTI_UNIVERSE = 'typeUniverse';
|
||||
|
||||
/// An embedded global used to collect and access startup metrics.
|
||||
const STARTUP_METRICS = 'sm';
|
||||
|
||||
/// Names that are supported by [JS_GET_NAME].
|
||||
// TODO(herhut): Make entries lower case (as in fields) and find a better name.
|
||||
enum JsGetName {
|
||||
|
|
|
@ -153,6 +153,11 @@ const Map<String, LibraryInfo> libraries = const {
|
|||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
"_rti": const LibraryInfo("_internal/js_runtime/lib/rti.dart",
|
||||
categories: "", documented: false, platforms: DART2JS_PLATFORM),
|
||||
"_dart2js_runtime_metrics": const LibraryInfo(
|
||||
"_internal/js_runtime/lib/dart2js_runtime_metrics.dart",
|
||||
categories: "",
|
||||
documented: false,
|
||||
platforms: DART2JS_PLATFORM),
|
||||
"_interceptors": const LibraryInfo(
|
||||
"_internal/js_runtime/lib/interceptors.dart",
|
||||
categories: "",
|
||||
|
|
|
@ -235,6 +235,9 @@
|
|||
"web_sql": {
|
||||
"uri": "web_sql/dart2js/web_sql_dart2js.dart"
|
||||
},
|
||||
"_dart2js_runtime_metrics": {
|
||||
"uri": "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
|
||||
},
|
||||
"_internal": {
|
||||
"uri": "internal/internal.dart",
|
||||
"patches": "_internal/js_runtime/lib/internal_patch.dart"
|
||||
|
@ -338,6 +341,9 @@
|
|||
"uri": "internal/internal.dart",
|
||||
"patches": "_internal/js_runtime/lib/internal_patch.dart"
|
||||
},
|
||||
"_dart2js_runtime_metrics": {
|
||||
"uri": "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
|
||||
},
|
||||
"_js_helper": {
|
||||
"uri": "_internal/js_runtime/lib/js_helper.dart"
|
||||
},
|
||||
|
@ -477,4 +483,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -233,6 +233,9 @@ dart2js:
|
|||
web_sql:
|
||||
uri: "web_sql/dart2js/web_sql_dart2js.dart"
|
||||
|
||||
_dart2js_runtime_metrics:
|
||||
uri: "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
|
||||
|
||||
_internal:
|
||||
uri: "internal/internal.dart"
|
||||
patches: "_internal/js_runtime/lib/internal_patch.dart"
|
||||
|
@ -334,6 +337,9 @@ dart2js_server:
|
|||
uri: "internal/internal.dart"
|
||||
patches: "_internal/js_runtime/lib/internal_patch.dart"
|
||||
|
||||
_dart2js_runtime_metrics:
|
||||
uri: "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
|
||||
|
||||
_js_helper:
|
||||
uri: "_internal/js_runtime/lib/js_helper.dart"
|
||||
|
||||
|
|
Loading…
Reference in a new issue