Skip to content

Move AdaptedHeapData to shared, as it will be used by console. #5079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import '../../../../../shared/analytics/analytics.dart' as ga;
import '../../../../../shared/analytics/constants.dart' as gac;
import '../../../../../shared/config_specific/import_export/import_export.dart';
import '../../../../../shared/globals.dart';
import '../../../../../shared/memory/class_name.dart';
import '../../../../../shared/primitives/auto_dispose.dart';
import '../../../../../shared/primitives/utils.dart';
import '../../../shared/heap/class_filter.dart';
import '../../../shared/heap/heap.dart';
import '../../../shared/heap/model.dart';
import '../../../shared/primitives/class_name.dart';
import '../../../shared/primitives/memory_utils.dart';
import 'heap_diff.dart';
import 'item_controller.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import 'package:flutter/foundation.dart';
import '../../../../../shared/analytics/analytics.dart' as ga;
import '../../../../../shared/analytics/constants.dart' as gac;
import '../../../../../shared/analytics/metrics.dart';
import '../../../../../shared/memory/class_name.dart';
import '../../../../../shared/primitives/utils.dart';
import '../../../shared/heap/heap.dart';
import '../../../shared/heap/model.dart';
import '../../../shared/primitives/class_name.dart';

/// Stores already calculated comparisons for heap couples.
class HeapDiffStore {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import 'package:flutter/foundation.dart';

import '../../../../../shared/memory/adapted_heap_data.dart';
import '../../../../../shared/primitives/auto_dispose.dart';
import '../../../shared/heap/heap.dart';
import '../../../shared/heap/model.dart';

abstract class SnapshotItem extends DisposableController {
/// Number, that if shown in name, should be unique in the list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import 'package:vm_service/vm_service.dart';

import '../../../../../shared/globals.dart';
import '../../../../../shared/memory/adapted_heap_data.dart';
import '../../../../../shared/memory/class_name.dart';
import '../../../shared/heap/heap.dart';
import '../../../shared/heap/model.dart';
import '../../../shared/primitives/class_name.dart';
import '../../../shared/primitives/instance_set_view.dart';

class HeapClassSampler extends ClassSampler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import '../../../../../shared/analytics/analytics.dart' as ga;
import '../../../../../shared/analytics/constants.dart' as gac;
import '../../../../../shared/common_widgets.dart';
import '../../../../../shared/dialogs.dart';
import '../../../../../shared/memory/class_name.dart';
import '../../../../../shared/theme.dart';
import '../../../../../shared/utils.dart';
import '../../../shared/heap/class_filter.dart';
import '../../../shared/primitives/class_name.dart';

String _adaptRootPackageForFilter(String? rootPackage) {
if (rootPackage == null || rootPackage.isEmpty) return '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import '../../../../../shared/analytics/analytics.dart' as ga;
import '../../../../../shared/analytics/constants.dart' as gac;
import '../../../../../shared/feature_flags.dart';
import '../../../../../shared/globals.dart';
import '../../../../../shared/memory/adapted_heap_data.dart';
import '../../../../../shared/primitives/utils.dart';
import '../../../../../shared/table/table.dart';
import '../../../../../shared/table/table_data.dart';
import '../../../../../shared/theme.dart';
import '../../../../../shared/utils.dart';
import '../../../shared/heap/heap.dart';
import '../../../shared/heap/model.dart';
import '../../../shared/primitives/instance_set_view.dart';
import '../../../shared/primitives/simple_elements.dart';
import '../../../shared/shared_memory_widgets.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'package:flutter/material.dart';
import 'package:leak_tracker/devtools_integration.dart';

import '../../../shared/heap/model.dart';
import '../../../../../shared/memory/adapted_heap_data.dart';
import '../../../shared/heap/spanning_tree.dart';
import 'model.dart';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'package:leak_tracker/devtools_integration.dart';
import 'package:vm_service/vm_service.dart';

import '../../../shared/heap/model.dart';
import '../../../../../shared/memory/adapted_heap_data.dart';

/// Names for json fields.
class _JsonFields {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import 'package:vm_service/vm_service.dart';

import '../../../../shared/memory/class_name.dart';
import '../../../../shared/table/table_data.dart';
import '../../../vm_developer/vm_service_private_extensions.dart';
import '../../shared/primitives/class_name.dart';

class AdaptedProfile {
AdaptedProfile.fromAllocationProfile(AllocationProfile profile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import 'package:flutter/widgets.dart';
import 'package:vm_service/vm_service.dart';

import '../../../../shared/globals.dart';
import '../../../../shared/memory/class_name.dart';
import '../../../../shared/primitives/auto_dispose.dart';
import '../../../../shared/primitives/utils.dart';
import '../../../../shared/table/table_data.dart';
import '../../../profiler/cpu_profile_model.dart';
import '../../../profiler/cpu_profile_transformer.dart';
import '../../shared/primitives/class_name.dart';

// TODO(bkonyi): make compatible with ClassHeapDetailStats for serialization /
// deserialization support.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import 'package:flutter/foundation.dart';

import '../primitives/class_name.dart';
import '../../../../shared/memory/class_name.dart';

enum ClassFilterType {
showAll,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../primitives/class_name.dart';
import '../../../../shared/memory/adapted_heap_data.dart';
import '../../../../shared/memory/class_name.dart';
import 'class_filter.dart';
import 'model.dart';
import 'spanning_tree.dart';
Expand Down
189 changes: 2 additions & 187 deletions packages/devtools_app/lib/src/screens/memory/shared/heap/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,135 +7,11 @@ import 'package:vm_service/vm_service.dart';
import '../../../../shared/analytics/analytics.dart' as ga;
import '../../../../shared/analytics/constants.dart' as gac;
import '../../../../shared/analytics/metrics.dart';
import '../../../../shared/memory/adapted_heap_data.dart';
import '../../../../shared/memory/class_name.dart';
import '../../../../shared/primitives/utils.dart';
import '../primitives/class_name.dart';
import '../primitives/memory_utils.dart';

/// Names for json fields.
class _JsonFields {
static const String objects = 'objects';
static const String code = 'code';
static const String references = 'references';
static const String klass = 'klass';
static const String library = 'library';
static const String shallowSize = 'shallowSize';
static const String rootIndex = 'rootIndex';
static const String created = 'created';
}

/// Contains information from [HeapSnapshotGraph],
/// needed for memory screen.
class AdaptedHeapData {
AdaptedHeapData(
this.objects, {
this.rootIndex = _defaultRootIndex,
DateTime? created,
}) : assert(objects.isNotEmpty),
assert(objects.length > rootIndex) {
this.created = created ?? DateTime.now();
}

factory AdaptedHeapData.fromJson(Map<String, dynamic> json) {
final createdJson = json[_JsonFields.created];

return AdaptedHeapData(
(json[_JsonFields.objects] as List<Object?>)
.map((e) => AdaptedHeapObject.fromJson(e as Map<String, Object?>))
.toList(),
created: createdJson == null ? null : DateTime.parse(createdJson),
rootIndex: json[_JsonFields.rootIndex] ?? _defaultRootIndex,
);
}

static AdaptedHeapData fromHeapSnapshot(
HeapSnapshotGraph graph,
) {
final objects = graph.objects.map((e) {
return AdaptedHeapObject.fromHeapSnapshotObject(e);
}).toList();

return AdaptedHeapData(objects);
}

/// Default value for rootIndex is taken from the doc:
/// https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/heap_snapshot.md#object-ids
static const int _defaultRootIndex = 1;

final int rootIndex;

AdaptedHeapObject get root => objects[rootIndex];

final List<AdaptedHeapObject> objects;

bool isSpanningTreeBuilt = false;

late DateTime created;

/// Heap objects by identityHashCode.
late final Map<IdentityHashCode, int> _objectsByCode = Map.fromIterable(
Iterable.generate(objects.length),
key: (i) => objects[i].code,
value: (i) => i,
);

Map<String, dynamic> toJson() => {
_JsonFields.objects: objects.map((e) => e.toJson()).toList(),
_JsonFields.rootIndex: rootIndex,
_JsonFields.created: created.toIso8601String(),
};

int? objectIndexByIdentityHashCode(IdentityHashCode code) =>
_objectsByCode[code];

HeapPath? retainingPath(int objectIndex) {
assert(isSpanningTreeBuilt);

if (objects[objectIndex].retainer == null) return null;

final result = <AdaptedHeapObject>[];

while (objectIndex >= 0) {
final object = objects[objectIndex];
result.add(object);
objectIndex = object.retainer!;
}

return HeapPath(result.reversed.toList(growable: false));
}

late final totalSize = () {
if (!isSpanningTreeBuilt) throw StateError('Spanning tree should be built');
return objects[rootIndex].retainedSize!;
}();
}

/// Result of invocation of [identityHashCode].
typedef IdentityHashCode = int;

/// Sequence of ids of objects in the heap.
class HeapPath {
HeapPath(this.objects);

final List<AdaptedHeapObject> objects;

late final bool isRetainedBySameClass = () {
if (objects.length < 2) return false;

final theClass = objects.last.heapClass;

return objects
.take(objects.length - 1)
.any((object) => object.heapClass == theClass);
}();

/// Retaining path for the object in string format.
String shortPath() => '/${objects.map((o) => o.shortName).join('/')}/';

/// Retaining path for the object as an array of the retaining objects.
List<String> detailedPath() =>
objects.map((o) => o.name).toList(growable: false);
}

/// Heap path represented by classes only, without object details.
class ClassOnlyHeapPath {
ClassOnlyHeapPath(HeapPath heapPath)
Expand Down Expand Up @@ -225,67 +101,6 @@ class ClassOnlyHeapPath {
int get hashCode => toLongString().hashCode;
}

/// Contains information from [HeapSnapshotObject] needed for
/// memory analysis on memory screen.
class AdaptedHeapObject {
AdaptedHeapObject({
required this.code,
required this.references,
required this.heapClass,
required this.shallowSize,
});

factory AdaptedHeapObject.fromHeapSnapshotObject(HeapSnapshotObject object) {
return AdaptedHeapObject(
code: object.identityHashCode,
references: List.of(object.references),
heapClass: HeapClassName.fromHeapSnapshotClass(object.klass),
shallowSize: object.shallowSize,
);
}

factory AdaptedHeapObject.fromJson(Map<String, Object?> json) =>
AdaptedHeapObject(
code: json[_JsonFields.code] as int,
references: (json[_JsonFields.references] as List<Object?>).cast<int>(),
heapClass: HeapClassName(
className: json[_JsonFields.klass] as String,
library: json[_JsonFields.library],
),
shallowSize: (json[_JsonFields.shallowSize] ?? 0) as int,
);

final List<int> references;
final HeapClassName heapClass;
final IdentityHashCode code;
final int shallowSize;

// No serialization is needed for the fields below, because the fields are
// calculated after the heap deserialization.

/// Special values: `null` - the object is not reachable,
/// `-1` - the object is root.
int? retainer;

/// Total shallow size of objects, where this object is retainer, recursively,
/// plus shallow size of this object.
///
/// Null, if object is not reachable.
int? retainedSize;

Map<String, dynamic> toJson() => {
_JsonFields.code: code,
_JsonFields.references: references,
_JsonFields.klass: heapClass.className,
_JsonFields.library: heapClass.library,
_JsonFields.shallowSize: shallowSize,
};

String get shortName => '${heapClass.className}-$code';

String get name => '${heapClass.library}/$shortName';
}

/// This class is needed to make the snapshot taking operation mockable.
class SnapshotTaker {
Future<AdaptedHeapData?> take() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'model.dart';
import '../../../../shared/memory/adapted_heap_data.dart';

/// Sets the field retainer and retainedSize for each object in the [heap], that
/// has retaining path to the root.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import 'package:flutter/widgets.dart';

import '../../../shared/analytics/constants.dart' as gac;
import '../../../shared/common_widgets.dart';
import '../../../shared/memory/class_name.dart';
import '../../../shared/theme.dart';
import 'primitives/class_name.dart';

class HeapClassView extends StatelessWidget {
const HeapClassView({
Expand Down
Loading