mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[flutter_driver] make timeline request in chunks (#58430)
Work-around large timeline data killing devicelab machines by requesting data in 1 second intervals and combining at the end. Non-breaking change to the driver API.
This commit is contained in:
parent
f4d26a3b85
commit
cd7dfd0a0a
@ -370,6 +370,10 @@ class VMServiceFlutterDriver extends FlutterDriver {
|
||||
: const <Map<String, dynamic>>[];
|
||||
}
|
||||
|
||||
Future<Map<String, Object>> _getVMTimelineMicros() async {
|
||||
return await _peer.sendRequest('getVMTimelineMicros') as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startTracing({
|
||||
List<TimelineStream> streams = const <TimelineStream>[TimelineStream.all],
|
||||
@ -397,15 +401,43 @@ class VMServiceFlutterDriver extends FlutterDriver {
|
||||
@override
|
||||
Future<Timeline> stopTracingAndDownloadTimeline({
|
||||
Duration timeout = kUnusuallyLongTimeout,
|
||||
int startTime,
|
||||
int endTime,
|
||||
}) async {
|
||||
assert(timeout != null);
|
||||
assert((startTime == null && endTime == null) ||
|
||||
(startTime != null && endTime != null));
|
||||
|
||||
try {
|
||||
await _warnIfSlow<void>(
|
||||
future: _peer.sendRequest(_setVMTimelineFlagsMethodName, <String, String>{'recordedStreams': '[]'}),
|
||||
timeout: timeout,
|
||||
message: 'VM is taking an unusually long time to respond to being told to stop tracing...',
|
||||
);
|
||||
return Timeline.fromJson(await _peer.sendRequest(_getVMTimelineMethodName) as Map<String, dynamic>);
|
||||
if (startTime == null) {
|
||||
return Timeline.fromJson(await _peer.sendRequest(_getVMTimelineMethodName) as Map<String, dynamic>);
|
||||
}
|
||||
const int kSecondInMicros = 1000000;
|
||||
int currentStart = startTime;
|
||||
int currentEnd = startTime + kSecondInMicros; // 1 second of timeline
|
||||
final List<Map<String, Object>> chunks = <Map<String, Object>>[];
|
||||
do {
|
||||
final Map<String, Object> chunk = await _peer.sendRequest(_getVMTimelineMethodName, <String, Object>{
|
||||
'timeOriginMicros': currentStart,
|
||||
// The range is inclusive, avoid double counting on the chance something
|
||||
// aligns on the boundary.
|
||||
'timeExtentMicros': kSecondInMicros - 1,
|
||||
}) as Map<String, dynamic>;
|
||||
chunks.add(chunk);
|
||||
currentStart = currentEnd;
|
||||
currentEnd += kSecondInMicros;
|
||||
} while (currentStart < endTime);
|
||||
return Timeline.fromJson(<String, Object>{
|
||||
'traceEvents': <Object> [
|
||||
for (Map<String, Object> chunk in chunks)
|
||||
...chunk['traceEvents'] as List<Object>,
|
||||
],
|
||||
});
|
||||
} catch (error, stackTrace) {
|
||||
throw DriverError(
|
||||
'Failed to stop tracing due to remote error',
|
||||
@ -434,13 +466,19 @@ class VMServiceFlutterDriver extends FlutterDriver {
|
||||
if (!retainPriorEvents) {
|
||||
await clearTimeline();
|
||||
}
|
||||
final Map<String, Object> startTimestamp = await _getVMTimelineMicros();
|
||||
await startTracing(streams: streams);
|
||||
await action();
|
||||
final Map<String, Object> endTimestamp = await _getVMTimelineMicros();
|
||||
|
||||
if (!(await _isPrecompiledMode())) {
|
||||
_log(_kDebugWarning);
|
||||
}
|
||||
return stopTracingAndDownloadTimeline();
|
||||
|
||||
return stopTracingAndDownloadTimeline(
|
||||
startTime: startTimestamp['timestamp'] as int,
|
||||
endTime: endTimestamp['timestamp'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -538,6 +538,12 @@ void main() {
|
||||
return null;
|
||||
});
|
||||
|
||||
when(mockPeer.sendRequest('getVMTimelineMicros'))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('getVMTimelineMicros');
|
||||
return <String, Object>{};
|
||||
});
|
||||
|
||||
when(mockPeer.sendRequest('setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[all]'}))))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('startTracing');
|
||||
@ -568,8 +574,10 @@ void main() {
|
||||
}, retainPriorEvents: true);
|
||||
|
||||
expect(log, const <String>[
|
||||
'getVMTimelineMicros',
|
||||
'startTracing',
|
||||
'action',
|
||||
'getVMTimelineMicros',
|
||||
'stopTracing',
|
||||
'download',
|
||||
]);
|
||||
@ -583,13 +591,77 @@ void main() {
|
||||
|
||||
expect(log, const <String>[
|
||||
'clear',
|
||||
'getVMTimelineMicros',
|
||||
'startTracing',
|
||||
'action',
|
||||
'getVMTimelineMicros',
|
||||
'stopTracing',
|
||||
'download',
|
||||
]);
|
||||
expect(timeline.events.single.name, 'test event');
|
||||
});
|
||||
|
||||
test('with time interval', () async {
|
||||
int count = 0;
|
||||
when(mockPeer.sendRequest('getVMTimelineMicros'))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('getVMTimelineMicros');
|
||||
return <String, Object>{
|
||||
if (count++ == 0)
|
||||
'timestamp': 0
|
||||
else
|
||||
'timestamp': 1000001,
|
||||
};
|
||||
});
|
||||
when(mockPeer.sendRequest('getVMTimeline', argThat(equals(<String, dynamic>{
|
||||
'timeOriginMicros': 0,
|
||||
'timeExtentMicros': 999999
|
||||
}))))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('download 1');
|
||||
return <String, dynamic>{
|
||||
'traceEvents': <dynamic>[
|
||||
<String, String>{
|
||||
'name': 'test event 1',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
when(mockPeer.sendRequest('getVMTimeline', argThat(equals(<String, dynamic>{
|
||||
'timeOriginMicros': 1000000,
|
||||
'timeExtentMicros': 999999,
|
||||
}))))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('download 2');
|
||||
return <String, dynamic>{
|
||||
'traceEvents': <dynamic>[
|
||||
<String, String>{
|
||||
'name': 'test event 2',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
final Timeline timeline = await driver.traceAction(() async {
|
||||
log.add('action');
|
||||
});
|
||||
|
||||
expect(log, const <String>[
|
||||
'clear',
|
||||
'getVMTimelineMicros',
|
||||
'startTracing',
|
||||
'action',
|
||||
'getVMTimelineMicros',
|
||||
'stopTracing',
|
||||
'download 1',
|
||||
'download 2',
|
||||
]);
|
||||
expect(timeline.events.map((TimelineEvent event) => event.name), <String>[
|
||||
'test event 1',
|
||||
'test event 2',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
group('traceAction with timeline streams', () {
|
||||
@ -598,6 +670,12 @@ void main() {
|
||||
bool startTracingCalled = false;
|
||||
bool stopTracingCalled = false;
|
||||
|
||||
when(mockPeer.sendRequest('getVMTimelineMicros'))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
log.add('getVMTimelineMicros');
|
||||
return <String, Object>{};
|
||||
});
|
||||
|
||||
when(mockPeer.sendRequest('setVMTimelineFlags', argThat(equals(<String, dynamic>{'recordedStreams': '[Dart, GC, Compiler]'}))))
|
||||
.thenAnswer((Invocation invocation) async {
|
||||
startTracingCalled = true;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user