Skip to content

Commit

Permalink
-
Browse files Browse the repository at this point in the history
  • Loading branch information
polina-c committed Apr 18, 2024
1 parent eddaa1f commit 756e46e
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 81 deletions.
230 changes: 149 additions & 81 deletions packages/devtools_app/lib/src/screens/memory/panes/profile/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,42 @@ import '../../../../shared/table/table_data.dart';
import '../../../vm_developer/vm_service_private_extensions.dart';
import '../../shared/heap/class_filter.dart';

class _Json {
static const rootPackage = 'root';
static const data = 'data';
class _ProfileJson {
static const total = 'total';
static const items = 'items';
static const newGC = 'newGC';
static const oldGC = 'oldGC';
static const totalGC = 'totalGC';
}

class AdaptedProfile {
AdaptedProfile._(
this.records,
this._total,
this._items,
this._itemsFiltered,
this.filter,
this.newSpaceGCStats,
this.oldSpaceGCStats,
this.totalGCStats,
);
AdaptedProfile._({
required ProfileRecord total,
required List<ProfileRecord> items,
required this.newSpaceGCStats,
required this.oldSpaceGCStats,
required this.totalGCStats,
}) : filter = ClassFilter.empty(),
_total = total,
_items = items,
_itemsFiltered = items;

AdaptedProfile.fromAllocationProfile(
factory AdaptedProfile.fromAllocationProfile(
AllocationProfile profile,
this.filter,
ClassFilter filter,
String? rootPackage,
) : newSpaceGCStats = profile.newSpaceGCStats,
oldSpaceGCStats = profile.oldSpaceGCStats,
totalGCStats = profile.totalGCStats {
_items = (profile.members ?? [])
.where((element) {
return element.bytesCurrent != 0 ||
element.newSpace.externalSize != 0 ||
element.oldSpace.externalSize != 0;
})
.map((e) => ProfileRecord.fromClassHeapStats(e))
.toList();

_itemsFiltered = _items
.where((element) => filter.apply(element.heapClass, rootPackage))
.toList();

_total = ProfileRecord.total(profile);

records = [
_total,
..._itemsFiltered,
];
) {
final result = AdaptedProfile._(
total: ProfileRecord.total(profile),
items: (profile.members ?? [])
.map((e) => ProfileRecord.fromClassHeapStats(e))
.toList(),
newSpaceGCStats: profile.newSpaceGCStats,
oldSpaceGCStats: profile.oldSpaceGCStats,
totalGCStats: profile.totalGCStats,
);

return AdaptedProfile.withNewFilter(result, filter, rootPackage);
}

AdaptedProfile.withNewFilter(
Expand All @@ -72,33 +65,33 @@ class AdaptedProfile {
extractClass: (s) => s.heapClass,
rootPackage: rootPackage,
);

records = [
_total,
..._itemsFiltered,
];
}

factory AdaptedProfile.fromJson(Map<String, dynamic> json) {
final profile =
AllocationProfile.fromJson(json[_Json.data] as Map<String, dynamic>);
final rootPackage = json[_Json.rootPackage] as String?;
return AdaptedProfile.fromAllocationProfile(
profile,
ClassFilter.empty(),
rootPackage,
);
}
// factory AdaptedProfile.fromJson(Map<String, dynamic> json) {
// return AdaptedProfile._(
// total: ,
// items: (profile.members ?? [])
// .map((e) => ProfileRecord.fromClassHeapStats(e))
// .toList(),
// newSpaceGCStats: profile.newSpaceGCStats,
// oldSpaceGCStats: profile.oldSpaceGCStats,
// totalGCStats: profile.totalGCStats,
// );
// }

Map<String, dynamic> toJson() {
return {
_Json.data: records,
_Json.rootPackage: rootPackage,
};
}
// Map<String, dynamic> toJson() {
// return {
// _Json.data: records,
// _Json.rootPackage: rootPackage,
// };
// }

/// A record per class plus one total record, with applied filter.
late final List<ProfileRecord> records;
late final List<ProfileRecord> records = _records ??= [
_total,
..._itemsFiltered,
];
List<ProfileRecord>? _records;

/// Record for totals.
late final ProfileRecord _total;
Expand All @@ -117,32 +110,69 @@ class AdaptedProfile {
final GCStats totalGCStats;
}

class _RecordJson {
static const isTotal = 'isTotal';
static const heapClass = 'heapClass';
static const totalInstances = 'totalInstances';
static const totalSize = 'totalSize';
static const totalDartHeapSize = 'totalDartHeapSize';
static const totalExternalSize = 'totalExternalSize';
static const newSpaceInstances = 'newSpaceInstances';
static const newSpaceSize = 'newSpaceSize';
static const newSpaceDartHeapSize = 'newSpaceDartHeapSize';
static const newSpaceExternalSize = 'newSpaceExternalSize';
static const oldSpaceInstances = 'oldSpaceInstances';
static const oldSpaceSize = 'oldSpaceSize';
static const oldSpaceDartHeapSize = 'oldSpaceDartHeapSize';
static const oldSpaceExternalSize = 'oldSpaceExternalSize';
}

class ProfileRecord with PinnableListEntry {
ProfileRecord.fromClassHeapStats(ClassHeapStats stats)
: assert(
stats.bytesCurrent! == stats.newSpace.size + stats.oldSpace.size,
'${stats.bytesCurrent}, ${stats.newSpace.size}, ${stats.oldSpace.size}',
),
isTotal = false,
heapClass = HeapClassName.fromClassRef(stats.classRef),
totalInstances = stats.instancesCurrent ?? 0,
totalSize = stats.bytesCurrent! +
stats.oldSpace.externalSize +
stats.newSpace.externalSize,
totalDartHeapSize = stats.bytesCurrent!,
totalExternalSize =
stats.oldSpace.externalSize + stats.newSpace.externalSize,
newSpaceInstances = stats.newSpace.count,
newSpaceSize = stats.newSpace.size + stats.newSpace.externalSize,
newSpaceDartHeapSize = stats.newSpace.size,
newSpaceExternalSize = stats.newSpace.externalSize,
oldSpaceInstances = stats.oldSpace.count,
oldSpaceSize = stats.oldSpace.size + stats.oldSpace.externalSize,
oldSpaceDartHeapSize = stats.oldSpace.size,
oldSpaceExternalSize = stats.oldSpace.externalSize {
ProfileRecord._({
required this.isTotal,
required this.heapClass,
required this.totalInstances,
required this.totalSize,
required this.totalDartHeapSize,
required this.totalExternalSize,
required this.newSpaceInstances,
required this.newSpaceSize,
required this.newSpaceDartHeapSize,
required this.newSpaceExternalSize,
required this.oldSpaceInstances,
required this.oldSpaceSize,
required this.oldSpaceDartHeapSize,
required this.oldSpaceExternalSize,
}) {
_verifyIntegrity();
}

factory ProfileRecord.fromClassHeapStats(ClassHeapStats stats) {
assert(
stats.bytesCurrent! == stats.newSpace.size + stats.oldSpace.size,
'${stats.bytesCurrent}, ${stats.newSpace.size}, ${stats.oldSpace.size}',
);
return ProfileRecord._(
isTotal: false,
heapClass: HeapClassName.fromClassRef(stats.classRef),
totalInstances: stats.instancesCurrent ?? 0,
totalSize: stats.bytesCurrent! +
stats.oldSpace.externalSize +
stats.newSpace.externalSize,
totalDartHeapSize: stats.bytesCurrent!,
totalExternalSize:
stats.oldSpace.externalSize + stats.newSpace.externalSize,
newSpaceInstances: stats.newSpace.count,
newSpaceSize: stats.newSpace.size + stats.newSpace.externalSize,
newSpaceDartHeapSize: stats.newSpace.size,
newSpaceExternalSize: stats.newSpace.externalSize,
oldSpaceInstances: stats.oldSpace.count,
oldSpaceSize: stats.oldSpace.size + stats.oldSpace.externalSize,
oldSpaceDartHeapSize: stats.oldSpace.size,
oldSpaceExternalSize: stats.oldSpace.externalSize,
);
}

ProfileRecord.total(AllocationProfile profile)
: isTotal = true,
heapClass =
Expand All @@ -163,6 +193,44 @@ class ProfileRecord with PinnableListEntry {
_verifyIntegrity();
}

factory ProfileRecord.fromJson(Map<String, dynamic> json) {
return ProfileRecord._(
isTotal: json[_RecordJson.isTotal] as bool,
heapClass: HeapClassName.fromJson(json[_RecordJson.heapClass]),
totalInstances: json[_RecordJson.totalInstances] as int?,
totalSize: json[_RecordJson.totalSize] as int,
totalDartHeapSize: json[_RecordJson.totalDartHeapSize] as int,
totalExternalSize: json[_RecordJson.totalExternalSize] as int,
newSpaceInstances: json[_RecordJson.newSpaceInstances] as int?,
newSpaceSize: json[_RecordJson.newSpaceSize] as int?,
newSpaceDartHeapSize: json[_RecordJson.newSpaceDartHeapSize] as int?,
newSpaceExternalSize: json[_RecordJson.newSpaceExternalSize] as int?,
oldSpaceInstances: json[_RecordJson.oldSpaceInstances] as int?,
oldSpaceSize: json[_RecordJson.oldSpaceSize] as int?,
oldSpaceDartHeapSize: json[_RecordJson.oldSpaceDartHeapSize] as int?,
oldSpaceExternalSize: json[_RecordJson.oldSpaceExternalSize] as int?,
);
}

Map<String, dynamic> toJson() {
return {
_RecordJson.isTotal: isTotal,
_RecordJson.heapClass: heapClass.toJson(),
_RecordJson.totalInstances: totalInstances,
_RecordJson.totalSize: totalSize,
_RecordJson.totalDartHeapSize: totalDartHeapSize,
_RecordJson.totalExternalSize: totalExternalSize,
_RecordJson.newSpaceInstances: newSpaceInstances,
_RecordJson.newSpaceSize: newSpaceSize,
_RecordJson.newSpaceDartHeapSize: newSpaceDartHeapSize,
_RecordJson.newSpaceExternalSize: newSpaceExternalSize,
_RecordJson.oldSpaceInstances: oldSpaceInstances,
_RecordJson.oldSpaceSize: oldSpaceSize,
_RecordJson.oldSpaceDartHeapSize: oldSpaceDartHeapSize,
_RecordJson.oldSpaceExternalSize: oldSpaceExternalSize,
};
}

final bool isTotal;

final HeapClassName heapClass;
Expand Down
19 changes: 19 additions & 0 deletions packages/devtools_app/lib/src/shared/memory/class_name.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ enum ClassType {
CircleIcon(color: color, text: label, textColor: Colors.white);
}

class _Json {
static const className = 'name';
static const library = 'lib';
}

/// Fully qualified Class name.
///
/// Equal class names are not stored twice in memory.
Expand All @@ -79,6 +84,20 @@ class HeapClassName {
HeapClassName({required String? library, required this.className})
: library = _normalizeLibrary(library);

factory HeapClassName.fromJson(Map<String, dynamic> json) {
return HeapClassName(
library: json[_Json.library] as String?,
className: json[_Json.className] as String,
);
}

Map<String, dynamic> toJson() {
return {
_Json.className: className,
_Json.library: library,
};
}

static final _instances = <HeapClassName>{};

static HeapClassName fromPath({
Expand Down

0 comments on commit 756e46e

Please sign in to comment.