@@ -34,13 +34,19 @@ class AdaptedProfile with Serializable {
3434 factory AdaptedProfile .fromAllocationProfile (
3535 AllocationProfile profile,
3636 ClassFilter filter,
37- String ? rootPackage,
38- ) {
37+ String ? rootPackage, {
38+ Set <String > pinnedClassFullNames = const {},
39+ }) {
3940 final adaptedProfile = AdaptedProfile ._(
4041 total: ProfileRecord .total (profile),
4142 items: (profile.members ?? [])
4243 .where ((e) => (e.instancesCurrent ?? 0 ) > 0 )
43- .map ((e) => ProfileRecord .fromClassHeapStats (e))
44+ .map ((e) => ProfileRecord .fromClassHeapStats (
45+ e,
46+ userPinned: pinnedClassFullNames.contains (
47+ HeapClassName .fromClassRef (e.classRef).fullName,
48+ ),
49+ ))
4450 .toList (),
4551 newSpaceGCStats: profile.newSpaceGCStats,
4652 oldSpaceGCStats: profile.oldSpaceGCStats,
@@ -70,6 +76,29 @@ class AdaptedProfile with Serializable {
7076 );
7177 }
7278
79+ /// Returns a copy of [profile] with [pinnedClassFullNames] applied to items.
80+ factory AdaptedProfile .withPinnedClasses (
81+ AdaptedProfile profile,
82+ Set <String > pinnedClassFullNames,
83+ String ? rootPackage,
84+ ) {
85+ final itemsWithPins = profile._items
86+ .map (
87+ (record) => record.copyWith (
88+ userPinned: pinnedClassFullNames.contains (record.heapClass.fullName),
89+ ),
90+ )
91+ .toList ();
92+ final updated = AdaptedProfile ._(
93+ total: profile._total,
94+ items: itemsWithPins,
95+ newSpaceGCStats: profile.newSpaceGCStats,
96+ oldSpaceGCStats: profile.oldSpaceGCStats,
97+ totalGCStats: profile.totalGCStats,
98+ );
99+ return AdaptedProfile .withNewFilter (updated, profile.filter, rootPackage);
100+ }
101+
73102 factory AdaptedProfile .fromJson (Map <String , dynamic > json) {
74103 return AdaptedProfile ._(
75104 total: ProfileRecord .fromJson (json[_ProfileJson .total]),
@@ -117,6 +146,7 @@ class AdaptedProfile with Serializable {
117146class _RecordJson {
118147 static const isTotal = 'it' ;
119148 static const heapClass = 'c' ;
149+ static const userPinned = 'p' ;
120150 static const totalInstances = 'ti' ;
121151 static const totalSize = 'ts' ;
122152 static const totalDartHeapSize = 'tds' ;
@@ -135,6 +165,7 @@ class ProfileRecord with PinnableListEntry, Serializable {
135165 ProfileRecord ._({
136166 required this .isTotal,
137167 required this .heapClass,
168+ this .userPinned = false ,
138169 required this .totalInstances,
139170 required this .totalSize,
140171 required this .totalDartHeapSize,
@@ -151,14 +182,18 @@ class ProfileRecord with PinnableListEntry, Serializable {
151182 _verifyIntegrity ();
152183 }
153184
154- factory ProfileRecord .fromClassHeapStats (ClassHeapStats stats) {
185+ factory ProfileRecord .fromClassHeapStats (
186+ ClassHeapStats stats, {
187+ bool userPinned = false ,
188+ }) {
155189 assert (
156190 stats.bytesCurrent! == stats.newSpace.size + stats.oldSpace.size,
157191 '${stats .bytesCurrent }, ${stats .newSpace .size }, ${stats .oldSpace .size }' ,
158192 );
159193 return ProfileRecord ._(
160194 isTotal: false ,
161195 heapClass: HeapClassName .fromClassRef (stats.classRef),
196+ userPinned: userPinned,
162197 totalInstances: stats.instancesCurrent ?? 0 ,
163198 totalSize:
164199 stats.bytesCurrent! +
@@ -180,6 +215,7 @@ class ProfileRecord with PinnableListEntry, Serializable {
180215
181216 ProfileRecord .total (AllocationProfile profile)
182217 : isTotal = true ,
218+ userPinned = false ,
183219 heapClass = HeapClassName .fromPath (className: 'All Classes' , library: '' ),
184220 totalInstances = null ,
185221 totalSize =
@@ -202,6 +238,7 @@ class ProfileRecord with PinnableListEntry, Serializable {
202238 return ProfileRecord ._(
203239 isTotal: json[_RecordJson .isTotal] as bool ,
204240 heapClass: HeapClassName .fromJson (json[_RecordJson .heapClass]),
241+ userPinned: json[_RecordJson .userPinned] as bool ? ?? false ,
205242 totalInstances: json[_RecordJson .totalInstances] as int ? ,
206243 totalSize: json[_RecordJson .totalSize] as int ,
207244 totalDartHeapSize: json[_RecordJson .totalDartHeapSize] as int ,
@@ -217,11 +254,32 @@ class ProfileRecord with PinnableListEntry, Serializable {
217254 );
218255 }
219256
257+ ProfileRecord copyWith ({bool ? userPinned}) {
258+ return ProfileRecord ._(
259+ isTotal: isTotal,
260+ heapClass: heapClass,
261+ userPinned: userPinned ?? this .userPinned,
262+ totalInstances: totalInstances,
263+ totalSize: totalSize,
264+ totalDartHeapSize: totalDartHeapSize,
265+ totalExternalSize: totalExternalSize,
266+ newSpaceInstances: newSpaceInstances,
267+ newSpaceSize: newSpaceSize,
268+ newSpaceDartHeapSize: newSpaceDartHeapSize,
269+ newSpaceExternalSize: newSpaceExternalSize,
270+ oldSpaceInstances: oldSpaceInstances,
271+ oldSpaceSize: oldSpaceSize,
272+ oldSpaceDartHeapSize: oldSpaceDartHeapSize,
273+ oldSpaceExternalSize: oldSpaceExternalSize,
274+ );
275+ }
276+
220277 @override
221278 Map <String , dynamic > toJson () {
222279 return {
223280 _RecordJson .isTotal: isTotal,
224281 _RecordJson .heapClass: heapClass,
282+ _RecordJson .userPinned: userPinned,
225283 _RecordJson .totalInstances: totalInstances,
226284 _RecordJson .totalSize: totalSize,
227285 _RecordJson .totalDartHeapSize: totalDartHeapSize,
@@ -239,6 +297,8 @@ class ProfileRecord with PinnableListEntry, Serializable {
239297
240298 final bool isTotal;
241299
300+ final bool userPinned;
301+
242302 final HeapClassName heapClass;
243303
244304 final int ? totalInstances;
@@ -257,7 +317,7 @@ class ProfileRecord with PinnableListEntry, Serializable {
257317 final int ? oldSpaceExternalSize;
258318
259319 @override
260- bool get pinToTop => isTotal;
320+ bool get pinToTop => isTotal || userPinned ;
261321
262322 void _verifyIntegrity () {
263323 assert (() {
0 commit comments