diffMemProfiles function

Future<MemDiffResult> diffMemProfiles(
  1. MemDiffInput input
)

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());
  }
}