dart-sdk/pkg/vm_service/test/get_stack_test.dart
Alexander Markov 058265f4e7 Reland "[vm] More efficient 'await' of not Future and completed _Future"
This is a reland of commit 6b3d1752fa

Fixes b/235734143
TEST=runtime/tests/vm/dart/await_in_custom_zone_test.dart

Original change's description:
> [vm] More efficient 'await' of not Future and completed _Future
>
> When awaiting a value which is not a Future or a completed
> built-in _Future, 'await' implementation can bypass heavyweight
> _Future/_FutureListener machinery and schedule micro-tasks directly.
>
> Benchmarks:
> JIT, x64:
> AsyncLiveVars.* +46-54% (bigger is better)
> Calls.AwaitAsyncCall -46% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -46%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -45%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -45%
> Calls.AwaitFutureOrCall -60%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -60%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -59%
>
> JIT, ia32:
> AsyncLiveVars.* +43-52% (bigger is better)
> Calls.AwaitAsyncCall -42% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -42%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -41%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -39%
> Calls.AwaitFutureOrCall -55%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -54%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -53%
>
> JIT, arm:
> AsyncLiveVars.* +64-71% (bigger is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -51% (less is better)
> Calls.AwaitAsyncCallClosureTargetPolymorphic -47%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -48%
> Calls.AwaitFutureOrCall -64%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -64%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -59%
>
> JIT, arm64:
> AsyncLiveVars.* +65-78% (bigger is better)
> Calls.AwaitAsyncCall -51% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -51%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -50%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -49%
> Calls.AwaitFutureOrCall -69%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -68%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -67%
>
> AOT, x64:
> AsyncLiveVars.* +55-61% (bigger is better)
> Calls.AwaitAsyncCall -47% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -46%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -47%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -46%
> Calls.AwaitFutureOrCall -59%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -59%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -58%
>
> AOT, arm:
> AsyncLiveVars.* 54-66% (bigger is better)
> Calls.AwaitAsyncCall -46-51% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -46-50%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -46-52%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -45-50%
> Calls.AwaitFutureOrCall -63-68%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -63-66%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -63-67%
>
> AOT, arm64:
> AsyncLiveVars.* +53-66% (bigger is better)
> Calls.AwaitAsyncCall -50-51% (less is better)
> Calls.AwaitAsyncCallInstanceTargetPolymorphic -50%
> Calls.AwaitAsyncCallClosureTargetPolymorphic -50-51%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphicManyAwaits -49-50%
> Calls.AwaitFutureOrCall -66-68%
> Calls.AwaitFutureOrCallInstanceTargetPolymorphic -66-68%
> Calls.AwaitFutureOrCallClosureTargetPolymorphic -63-67%
>
> TEST=ci
> Issue: https://github.com/dart-lang/sdk/issues/48378
>
> Change-Id: I65e3702fcd816ee3fee876ff442b9887c035b1ec
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243102
> Reviewed-by: Lasse Nielsen <lrn@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>

Change-Id: I245984ace1c768fdcba58dfdd6aa46e52126be4e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/248442
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
2022-06-15 15:35:38 +00:00

159 lines
5.8 KiB
Dart

// Copyright (c) 2020, 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.
// VMOptions=--verbose_debug
import 'dart:developer';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
const LINE_A = 33;
const LINE_B = 35;
Future<void> testMain() async {
await func1();
}
Future func1() async => await func2();
Future func2() async => await func3();
Future func3() async => await func4();
Future func4() async => await func5();
Future func5() async => await func6();
Future func6() async => await func7();
Future func7() async => await func8();
Future func8() async => await func9();
Future func9() async => await func10();
Future func10() async {
debugger(); // LINE_A
await 0;
debugger(); // LINE_B
print("Hello, world!");
}
void expectFrame(
final frame, final kindExpectation, final codeNameExpectation) {
expect(frame.kind, kindExpectation);
expect(frame.code?.name, codeNameExpectation);
}
void expectFrames(final frames, final expectKindAndCodeName) {
for (int i = 0; i < expectKindAndCodeName.length; i++) {
expectFrame(
frames[i], expectKindAndCodeName[i][0], expectKindAndCodeName[i][1]);
}
}
final tests = <IsolateTest>[
// Before the first await.
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_A),
// At LINE_A we're still running sync. so no asyncCausalFrames.
(VmService service, IsolateRef isolateRef) async {
final result = await service.getStack(isolateRef.id!);
expect(result.frames, hasLength(16));
expect(result.asyncCausalFrames, isNull);
expect(result.awaiterFrames, hasLength(16));
expectFrames(result.frames, [
[equals('Regular'), endsWith(' func10')],
[equals('Regular'), endsWith(' func9')],
[equals('Regular'), endsWith(' func8')],
[equals('Regular'), endsWith(' func7')],
[equals('Regular'), endsWith(' func6')],
[equals('Regular'), endsWith(' func5')],
[equals('Regular'), endsWith(' func4')],
[equals('Regular'), endsWith(' func3')],
[equals('Regular'), endsWith(' func2')],
[equals('Regular'), endsWith(' func1')],
[equals('Regular'), endsWith(' testMain')],
]);
expectFrames(result.awaiterFrames, [
[equals('AsyncActivation'), endsWith(' func10')],
[equals('AsyncActivation'), endsWith(' func9')],
[equals('AsyncActivation'), endsWith(' func8')],
[equals('AsyncActivation'), endsWith(' func7')],
[equals('AsyncActivation'), endsWith(' func6')],
[equals('AsyncActivation'), endsWith(' func5')],
[equals('AsyncActivation'), endsWith(' func4')],
[equals('AsyncActivation'), endsWith(' func3')],
[equals('AsyncActivation'), endsWith(' func2')],
[equals('AsyncActivation'), endsWith(' func1')],
[equals('AsyncActivation'), endsWith(' testMain')],
]);
},
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_B),
// After resuming the continuation - i.e. running async.
(VmService service, IsolateRef isolateRef) async {
final result = await service.getStack(isolateRef.id!);
expect(result.frames, hasLength(6));
expect(result.asyncCausalFrames, hasLength(26));
expect(result.awaiterFrames, hasLength(13));
expectFrames(result.frames!, [
[equals('Regular'), endsWith(' func10')],
[equals('Regular'), endsWith(' _RootZone.runUnary')],
[equals('Regular'), anything], // Internal mech. ..
[equals('Regular'), anything],
[equals('Regular'), anything],
[equals('Regular'), endsWith(' _RawReceivePortImpl._handleMessage')],
]);
expectFrames(result.asyncCausalFrames, [
[equals('Regular'), endsWith(' func10')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func9')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func8')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func7')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func6')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func5')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func4')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func3')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func2')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' func1')],
[equals('AsyncSuspensionMarker'), isNull],
[equals('AsyncCausal'), endsWith(' testMain')],
[equals('AsyncSuspensionMarker'), isNull],
]);
expectFrames(result.awaiterFrames, [
[equals('AsyncActivation'), endsWith(' func10')],
[equals('AsyncActivation'), endsWith(' func9')],
[equals('AsyncActivation'), endsWith(' func8')],
[equals('AsyncActivation'), endsWith(' func7')],
[equals('AsyncActivation'), endsWith(' func6')],
[equals('AsyncActivation'), endsWith(' func5')],
[equals('AsyncActivation'), endsWith(' func4')],
[equals('AsyncActivation'), endsWith(' func3')],
[equals('AsyncActivation'), endsWith(' func2')],
[equals('AsyncActivation'), endsWith(' func1')],
[equals('AsyncActivation'), endsWith(' testMain')],
[equals('AsyncActivation'), endsWith(' _ServiceTesteeRunner.run')],
[equals('AsyncActivation'), endsWith(' runIsolateTests')],
]);
},
];
main([args = const <String>[]]) => runIsolateTests(
args,
tests,
'get_stack_test.dart',
testeeConcurrent: testMain,
);