@@ -153,8 +153,8 @@ class CpuProfilePair {
153153 required String processId,
154154 }) async {
155155 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);
158158 }
159159 }
160160}
@@ -166,11 +166,13 @@ class CpuProfileData with Serializable {
166166 required this .cpuSamples,
167167 required this .profileMetaData,
168168 required this .rootedAtTags,
169- }) {
170- _cpuProfileRoot = CpuStackFrame .root (profileMetaData);
171- }
169+ }) : cpuProfileRoot = CpuStackFrame .root (profileMetaData);
172170
173171 factory CpuProfileData .fromJson (Map <String , Object ?> json_) {
172+ if (json_.isEmpty) {
173+ return CpuProfileData .empty ();
174+ }
175+
174176 final json = _CpuProfileDataJson (json_);
175177
176178 // All CPU samples.
@@ -187,15 +189,17 @@ class CpuProfileData with Serializable {
187189 final samplePeriod =
188190 observedSamplePeriod (samples) ?? json.samplePeriod ?? 0 ;
189191
192+ final timeOriginMicros = json.timeOriginMicros;
193+ final timeExtentMicros = json.timeExtentMicros;
190194 final profileMetaData = CpuProfileMetaData (
191195 sampleCount: json.sampleCount ?? 0 ,
192196 samplePeriod: samplePeriod,
193197 stackDepth: json.stackDepth ?? 0 ,
194- time: (json. timeOriginMicros != null && json. timeExtentMicros != null )
198+ time: (timeOriginMicros != null && timeExtentMicros != null )
195199 ? (TimeRange ()
196- ..start = Duration (microseconds: json. timeOriginMicros! )
200+ ..start = Duration (microseconds: timeOriginMicros)
197201 ..end = Duration (
198- microseconds: json. timeOriginMicros! + json. timeExtentMicros! ,
202+ microseconds: timeOriginMicros + timeExtentMicros,
199203 ))
200204 : null ,
201205 );
@@ -329,10 +333,10 @@ class CpuProfileData with Serializable {
329333 });
330334
331335 for (final sample in tagProfile.cpuSamples) {
332- String ? updatedId = idMapping[sample.leafId];
336+ String ? updatedId = idMapping[sample.leafId]! ;
333337 samples.add (
334338 CpuSampleEvent (
335- leafId: updatedId! ,
339+ leafId: updatedId,
336340 userTag: sample.userTag,
337341 vmTag: sample.vmTag,
338342 traceJson: sample.toJson,
@@ -540,7 +544,17 @@ class CpuProfileData with Serializable {
540544 );
541545 }
542546
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+ );
544558
545559 /// Generates [CpuProfileData] from the provided [cpuSamples] .
546560 ///
@@ -556,45 +570,48 @@ class CpuProfileData with Serializable {
556570 // of all stacks, regardless of entrypoint. This should never be seen in the
557571 // final output from this method.
558572 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+ );
575584
576585 // Build the trace events.
586+ final traceEvents = < Map <String , Object ?>> [];
577587 for (final sample in cpuSamples.samples ?? < vm_service.CpuSample > []) {
578588 final tree = _CpuProfileTimelineTree .getTreeFromSample (sample)! ;
579589 // Skip the root.
580590 if (tree.frameId == kRootId) {
581591 continue ;
582592 }
583- (traceObject[ CpuProfileData ._traceEventsKey] ! as List < Object ?>) .add ({
593+ traceEvents .add ({
584594 'ph' : 'P' , // kind = sample event
585595 'name' : '' , // Blank to keep about:tracing happy
586596 'pid' : cpuSamples.pid,
587597 'tid' : sample.tid,
588598 'ts' : sample.timestamp,
589599 'cat' : 'Dart' ,
590600 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},
595602 });
596603 }
597604
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+
598615 await _addPackageUrisToTraceObject (isolateId, traceObject);
599616
600617 return CpuProfileData .fromJson (traceObject);
@@ -674,6 +691,8 @@ class CpuProfileData with Serializable {
674691
675692 final CpuProfileMetaData profileMetaData;
676693
694+ final CpuStackFrame cpuProfileRoot;
695+
677696 /// `true` if the CpuProfileData has tag-based roots.
678697 ///
679698 /// This value is used during the bottom-up transformation to ensure that the
@@ -687,7 +706,7 @@ class CpuProfileData with Serializable {
687706 if (! processed) return < CpuStackFrame > [];
688707 return _callTreeRoots ?? = [
689708 // Don't display the root node.
690- ..._cpuProfileRoot. children. map ((e) => e .deepCopy () ),
709+ for ( final rootChild in cpuProfileRoot. children) rootChild .deepCopy (),
691710 ];
692711 }
693712
@@ -703,49 +722,23 @@ class CpuProfileData with Serializable {
703722 assert (_bottomUpRoots == null );
704723 _bottomUpRoots = await BottomUpTransformer <CpuStackFrame >()
705724 .bottomUpRootsFor (
706- topDownRoot: _cpuProfileRoot ,
725+ topDownRoot: cpuProfileRoot ,
707726 mergeSamples: mergeCpuProfileRoots,
708727 rootedAtTags: rootedAtTags,
709728 );
710729 }
711730
712731 List <CpuStackFrame >? _bottomUpRoots;
713732
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+ };
747737
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+ };
749742
750743 CpuStackFrame ? selectedStackFrame;
751744
@@ -755,24 +748,20 @@ class CpuProfileData with Serializable {
755748 _samplePeriodKey: profileMetaData.samplePeriod,
756749 _sampleCountKey: profileMetaData.sampleCount,
757750 _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,
762755 _stackFramesKey: stackFramesJson,
763756 _traceEventsKey: cpuSamples.map ((sample) => sample.toJson).toList (),
764757 };
765758
766759 bool get isEmpty => profileMetaData.sampleCount == 0 ;
767760
768761 @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+ };
776765}
777766
778767extension type _CpuProfileDataJson (Map <String , Object ?> json) {
@@ -978,7 +967,7 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
978967
979968 @override
980969 String get tooltip {
981- var prefix = '' ;
970+ final String ? prefix ;
982971 if (isNative) {
983972 prefix = '[Native]' ;
984973 } else if (isDartCore) {
@@ -987,8 +976,10 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
987976 prefix = '[Flutter]' ;
988977 } else if (isTag) {
989978 prefix = '[Tag]' ;
979+ } else {
980+ prefix = null ;
990981 }
991- final nameWithPrefix = [prefix, name].join (' ' );
982+ final nameWithPrefix = [? prefix, name].join (' ' );
992983 return [
993984 nameWithPrefix,
994985 durationText (totalTime),
@@ -1074,7 +1065,7 @@ class CpuStackFrame extends TreeNode<CpuStackFrame>
10741065 CpuProfileData .resolvedUrlKey: rawUrl,
10751066 CpuProfileData .resolvedPackageUriKey: packageUri,
10761067 CpuProfileData .sourceLineKey: sourceLine,
1077- if (parentId != null ) CpuProfileData .parentIdKey: parentId,
1068+ CpuProfileData .parentIdKey: ? parentId,
10781069 },
10791070 };
10801071
0 commit comments