@@ -153,8 +153,8 @@ class CpuProfilePair {
153
153
required String processId,
154
154
}) async {
155
155
await transformer.processData (functionProfile, processId: processId);
156
- if (codeProfile != null ) {
157
- await transformer.processData (codeProfile! , processId: processId);
156
+ if (codeProfile case final codeProfile ? ) {
157
+ await transformer.processData (codeProfile, processId: processId);
158
158
}
159
159
}
160
160
}
@@ -166,11 +166,13 @@ class CpuProfileData with Serializable {
166
166
required this .cpuSamples,
167
167
required this .profileMetaData,
168
168
required this .rootedAtTags,
169
- }) {
170
- _cpuProfileRoot = CpuStackFrame .root (profileMetaData);
171
- }
169
+ }) : cpuProfileRoot = CpuStackFrame .root (profileMetaData);
172
170
173
171
factory CpuProfileData .fromJson (Map <String , Object ?> json_) {
172
+ if (json_.isEmpty) {
173
+ return CpuProfileData .empty ();
174
+ }
175
+
174
176
final json = _CpuProfileDataJson (json_);
175
177
176
178
// All CPU samples.
@@ -187,15 +189,17 @@ class CpuProfileData with Serializable {
187
189
final samplePeriod =
188
190
observedSamplePeriod (samples) ?? json.samplePeriod ?? 0 ;
189
191
192
+ final timeOriginMicros = json.timeOriginMicros;
193
+ final timeExtentMicros = json.timeExtentMicros;
190
194
final profileMetaData = CpuProfileMetaData (
191
195
sampleCount: json.sampleCount ?? 0 ,
192
196
samplePeriod: samplePeriod,
193
197
stackDepth: json.stackDepth ?? 0 ,
194
- time: (json. timeOriginMicros != null && json. timeExtentMicros != null )
198
+ time: (timeOriginMicros != null && timeExtentMicros != null )
195
199
? (TimeRange ()
196
- ..start = Duration (microseconds: json. timeOriginMicros! )
200
+ ..start = Duration (microseconds: timeOriginMicros)
197
201
..end = Duration (
198
- microseconds: json. timeOriginMicros! + json. timeExtentMicros! ,
202
+ microseconds: timeOriginMicros + timeExtentMicros,
199
203
))
200
204
: null ,
201
205
);
@@ -329,10 +333,10 @@ class CpuProfileData with Serializable {
329
333
});
330
334
331
335
for (final sample in tagProfile.cpuSamples) {
332
- String ? updatedId = idMapping[sample.leafId];
336
+ String ? updatedId = idMapping[sample.leafId]! ;
333
337
samples.add (
334
338
CpuSampleEvent (
335
- leafId: updatedId! ,
339
+ leafId: updatedId,
336
340
userTag: sample.userTag,
337
341
vmTag: sample.vmTag,
338
342
traceJson: sample.toJson,
@@ -540,7 +544,17 @@ class CpuProfileData with Serializable {
540
544
);
541
545
}
542
546
543
- factory CpuProfileData .empty () => CpuProfileData .fromJson ({});
547
+ factory CpuProfileData .empty () => CpuProfileData ._(
548
+ stackFrames: {},
549
+ cpuSamples: [],
550
+ profileMetaData: CpuProfileMetaData (
551
+ sampleCount: 0 ,
552
+ samplePeriod: 0 ,
553
+ stackDepth: 0 ,
554
+ time: null ,
555
+ ),
556
+ rootedAtTags: false ,
557
+ );
544
558
545
559
/// Generates [CpuProfileData] from the provided [cpuSamples] .
546
560
///
@@ -556,45 +570,48 @@ class CpuProfileData with Serializable {
556
570
// of all stacks, regardless of entrypoint. This should never be seen in the
557
571
// final output from this method.
558
572
const kRootId = 0 ;
559
- final traceObject = < String , Object ? > {
560
- CpuProfileData ._sampleCountKey: cpuSamples.sampleCount,
561
- CpuProfileData ._samplePeriodKey: cpuSamples.samplePeriod,
562
- CpuProfileData ._stackDepthKey: cpuSamples.maxStackDepth,
563
- CpuProfileData ._timeOriginKey: cpuSamples.timeOriginMicros,
564
- CpuProfileData ._timeExtentKey: cpuSamples.timeExtentMicros,
565
- CpuProfileData ._stackFramesKey: cpuSamples.generateStackFramesJson (
566
- isolateId: isolateId,
567
- // We want to ensure that if [kRootId] ever changes, this change is
568
- // propagated to [cpuSamples.generateStackFramesJson].
569
- // ignore: avoid_redundant_argument_values
570
- kRootId: kRootId,
571
- buildCodeTree: buildCodeTree,
572
- ),
573
- CpuProfileData ._traceEventsKey: [],
574
- };
573
+
574
+ // Generate the stack frames first as it builds and tracks
575
+ // the timeline tree for each sample.
576
+ final stackFrames = cpuSamples.generateStackFramesJson (
577
+ isolateId: isolateId,
578
+ // We want to ensure that if [kRootId] ever changes, this change is
579
+ // propagated to [cpuSamples.generateStackFramesJson].
580
+ // ignore: avoid_redundant_argument_values
581
+ kRootId: kRootId,
582
+ buildCodeTree: buildCodeTree,
583
+ );
575
584
576
585
// Build the trace events.
586
+ final traceEvents = < Map <String , Object ?>> [];
577
587
for (final sample in cpuSamples.samples ?? < vm_service.CpuSample > []) {
578
588
final tree = _CpuProfileTimelineTree .getTreeFromSample (sample)! ;
579
589
// Skip the root.
580
590
if (tree.frameId == kRootId) {
581
591
continue ;
582
592
}
583
- (traceObject[ CpuProfileData ._traceEventsKey] ! as List < Object ?>) .add ({
593
+ traceEvents .add ({
584
594
'ph' : 'P' , // kind = sample event
585
595
'name' : '' , // Blank to keep about:tracing happy
586
596
'pid' : cpuSamples.pid,
587
597
'tid' : sample.tid,
588
598
'ts' : sample.timestamp,
589
599
'cat' : 'Dart' ,
590
600
CpuProfileData .stackFrameIdKey: '$isolateId -${tree .frameId }' ,
591
- 'args' : {
592
- if (sample.userTag != null ) userTagKey: sample.userTag,
593
- if (sample.vmTag != null ) vmTagKey: sample.vmTag,
594
- },
601
+ 'args' : {userTagKey: ? sample.userTag, vmTagKey: ? sample.vmTag},
595
602
});
596
603
}
597
604
605
+ final traceObject = < String , Object ? > {
606
+ CpuProfileData ._sampleCountKey: cpuSamples.sampleCount,
607
+ CpuProfileData ._samplePeriodKey: cpuSamples.samplePeriod,
608
+ CpuProfileData ._stackDepthKey: cpuSamples.maxStackDepth,
609
+ CpuProfileData ._timeOriginKey: cpuSamples.timeOriginMicros,
610
+ CpuProfileData ._timeExtentKey: cpuSamples.timeExtentMicros,
611
+ CpuProfileData ._stackFramesKey: stackFrames,
612
+ CpuProfileData ._traceEventsKey: traceEvents,
613
+ };
614
+
598
615
await _addPackageUrisToTraceObject (isolateId, traceObject);
599
616
600
617
return CpuProfileData .fromJson (traceObject);
@@ -674,6 +691,8 @@ class CpuProfileData with Serializable {
674
691
675
692
final CpuProfileMetaData profileMetaData;
676
693
694
+ final CpuStackFrame cpuProfileRoot;
695
+
677
696
/// `true` if the CpuProfileData has tag-based roots.
678
697
///
679
698
/// This value is used during the bottom-up transformation to ensure that the
@@ -687,7 +706,7 @@ class CpuProfileData with Serializable {
687
706
if (! processed) return < CpuStackFrame > [];
688
707
return _callTreeRoots ?? = [
689
708
// Don't display the root node.
690
- ..._cpuProfileRoot. children. map ((e) => e .deepCopy () ),
709
+ for ( final rootChild in cpuProfileRoot. children) rootChild .deepCopy (),
691
710
];
692
711
}
693
712
@@ -703,49 +722,23 @@ class CpuProfileData with Serializable {
703
722
assert (_bottomUpRoots == null );
704
723
_bottomUpRoots = await BottomUpTransformer <CpuStackFrame >()
705
724
.bottomUpRootsFor (
706
- topDownRoot: _cpuProfileRoot ,
725
+ topDownRoot: cpuProfileRoot ,
707
726
mergeSamples: mergeCpuProfileRoots,
708
727
rootedAtTags: rootedAtTags,
709
728
);
710
729
}
711
730
712
731
List <CpuStackFrame >? _bottomUpRoots;
713
732
714
- CpuStackFrame get cpuProfileRoot => _cpuProfileRoot;
715
-
716
- Iterable <String > get userTags {
717
- if (_userTags != null ) {
718
- return _userTags! ;
719
- }
720
- final tags = < String > {};
721
- for (final cpuSample in cpuSamples) {
722
- final tag = cpuSample.userTag;
723
- if (tag != null ) {
724
- tags.add (tag);
725
- }
726
- }
727
- _userTags = tags;
728
- return _userTags! ;
729
- }
730
-
731
- Iterable <String > get vmTags {
732
- if (_vmTags != null ) {
733
- return _vmTags! ;
734
- }
735
- final tags = < String > {};
736
- for (final cpuSample in cpuSamples) {
737
- final tag = cpuSample.vmTag;
738
- if (tag != null ) {
739
- tags.add (tag);
740
- }
741
- }
742
- return _vmTags = tags;
743
- }
744
-
745
- Iterable <String >? _userTags;
746
- Iterable <String >? _vmTags;
733
+ late final Iterable <String > userTags = {
734
+ for (final cpuSample in cpuSamples)
735
+ if (cpuSample.userTag case final userTag? ) userTag,
736
+ };
747
737
748
- late final CpuStackFrame _cpuProfileRoot;
738
+ late final Iterable <String > vmTags = {
739
+ for (final cpuSample in cpuSamples)
740
+ if (cpuSample.vmTag case final vmTag? ) vmTag,
741
+ };
749
742
750
743
CpuStackFrame ? selectedStackFrame;
751
744
@@ -755,24 +748,20 @@ class CpuProfileData with Serializable {
755
748
_samplePeriodKey: profileMetaData.samplePeriod,
756
749
_sampleCountKey: profileMetaData.sampleCount,
757
750
_stackDepthKey: profileMetaData.stackDepth,
758
- if (profileMetaData.time? .start != null )
759
- _timeOriginKey: profileMetaData.time ! .start ! .inMicroseconds,
760
- if (profileMetaData.time? .duration != null )
761
- _timeExtentKey: profileMetaData.time ! . duration.inMicroseconds,
751
+ if (profileMetaData.time? .start case final startTime ? )
752
+ _timeOriginKey: startTime .inMicroseconds,
753
+ if (profileMetaData.time? .duration case final duration ? )
754
+ _timeExtentKey: duration.inMicroseconds,
762
755
_stackFramesKey: stackFramesJson,
763
756
_traceEventsKey: cpuSamples.map ((sample) => sample.toJson).toList (),
764
757
};
765
758
766
759
bool get isEmpty => profileMetaData.sampleCount == 0 ;
767
760
768
761
@visibleForTesting
769
- Map <String , Object ?> get stackFramesJson {
770
- final framesJson = < String , Object ? > {};
771
- for (final sf in stackFrames.values) {
772
- framesJson.addAll (sf.toJson);
773
- }
774
- return framesJson;
775
- }
762
+ Map <String , Object ?> get stackFramesJson => {
763
+ for (final sf in stackFrames.values) ...sf.toJson,
764
+ };
776
765
}
777
766
778
767
extension type _CpuProfileDataJson (Map <String , Object ?> json) {
@@ -978,7 +967,7 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
978
967
979
968
@override
980
969
String get tooltip {
981
- var prefix = '' ;
970
+ final String ? prefix ;
982
971
if (isNative) {
983
972
prefix = '[Native]' ;
984
973
} else if (isDartCore) {
@@ -987,8 +976,10 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
987
976
prefix = '[Flutter]' ;
988
977
} else if (isTag) {
989
978
prefix = '[Tag]' ;
979
+ } else {
980
+ prefix = null ;
990
981
}
991
- final nameWithPrefix = [prefix, name].join (' ' );
982
+ final nameWithPrefix = [? prefix, name].join (' ' );
992
983
return [
993
984
nameWithPrefix,
994
985
durationText (totalTime),
@@ -1074,7 +1065,7 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
1074
1065
CpuProfileData .resolvedUrlKey: rawUrl,
1075
1066
CpuProfileData .resolvedPackageUriKey: packageUri,
1076
1067
CpuProfileData .sourceLineKey: sourceLine,
1077
- if (parentId != null ) CpuProfileData .parentIdKey: parentId,
1068
+ CpuProfileData .parentIdKey: ? parentId,
1078
1069
},
1079
1070
};
1080
1071
0 commit comments