diffMemProfiles function
Computes the allocation diff between two profile files.
Never throws; all error conditions are represented as sealed result cases.
Implementation
Future<MemDiffResult> diffMemProfiles(MemDiffInput input) async {
try {
final (beforeErr, beforeProfile) = await _loadProfile(input.beforePath);
if (beforeErr != null) return MemDiffReadError(beforeErr);
final (afterErr, afterProfile) = await _loadProfile(input.afterPath);
if (afterErr != null) return MemDiffReadError(afterErr);
final b = beforeProfile!;
final a = afterProfile!;
if (b.isolateId != a.isolateId && b.isolateName != a.isolateName) {
return MemDiffIsolateMismatch(beforeIsolateName: b.isolateName, afterIsolateName: a.isolateName);
}
final beforeMap = {for (final c in b.classes) '${c.className}|${c.libraryUri}': c};
final afterMap = {for (final c in a.classes) '${c.className}|${c.libraryUri}': c};
final diffs = <ClassDiff>[];
for (final key in {...beforeMap.keys, ...afterMap.keys}) {
final bc = beforeMap[key];
final ac = afterMap[key];
final instancesBefore = bc?.instancesCurrent ?? 0;
final instancesAfter = ac?.instancesCurrent ?? 0;
final bytesBefore = bc?.bytesCurrent ?? 0;
final bytesAfter = ac?.bytesCurrent ?? 0;
if (instancesBefore == instancesAfter && bytesBefore == bytesAfter) continue;
final ref = bc ?? ac!;
diffs.add(ClassDiff(
className: ref.className,
libraryUri: ref.libraryUri,
instancesBefore: instancesBefore,
instancesAfter: instancesAfter,
bytesBefore: bytesBefore,
bytesAfter: bytesAfter,
));
}
diffs.sort((x, y) => input.sort == MemDiffSort.bytes
? y.bytesDelta.abs().compareTo(x.bytesDelta.abs())
: y.instanceDelta.abs().compareTo(x.instanceDelta.abs()));
return MemDiffSuccess(
diffs: input.topN != null ? diffs.take(input.topN!).toList() : diffs,
beforeIsolateName: b.isolateName,
afterIsolateName: a.isolateName,
sort: input.sort,
);
} catch (e) {
return MemDiffError(e.toString());
}
}