computeHistogram function

Histogram computeHistogram(
  1. ProgramInfo info,
  2. HistogramType type, {
  3. String? filter,
})

Construct the histogram of specific type given a ProgramInfo.

filter glob can be provided to skip some of the nodes in the info: a string is created which contains library name, class name and function name for the given node and if this string does not match the filter glob then this node is ignored.

Implementation

Histogram computeHistogram(ProgramInfo info, HistogramType type,
    {String? filter}) {
  bool Function(String, String?, String?) matchesFilter;

  if (filter != null) {
    final re = RegExp(filter.replaceAll('*', '.*'), caseSensitive: false);
    matchesFilter =
        (lib, cls, fun) => re.hasMatch("$lib::${cls ?? ''}.${fun ?? ''}");
  } else {
    matchesFilter = (_, __, ___) => true;
  }

  if (type == HistogramType.byNodeType) {
    final Set<int> filteredNodes = {};
    if (filter != null) {
      info.visit((pkg, lib, cls, fun, node) {
        if (matchesFilter(lib, cls, fun)) {
          filteredNodes.add(node.id);
        }
      });
    }

    final snapshotInfo = info.snapshotInfo!;

    return Histogram.fromIterable<Node>(
        snapshotInfo.snapshot.nodes.where((n) =>
            filter == null ||
            filteredNodes.contains(snapshotInfo.ownerOf(n).id)),
        sizeOf: (n) {
          return n.selfSize;
        },
        bucketFor: (n) => n.type,
        bucketInfo: const BucketInfo(nameComponents: ['Type']));
  } else {
    final buckets = <String, int>{};
    final bucketing = Bucketing._forType[type]!;

    info.visit((pkg, lib, cls, fun, node) {
      final sz = node.size;
      if (sz == null || sz == 0) {
        return;
      }
      if (!matchesFilter(lib, cls, fun)) {
        return;
      }
      final bucket = bucketing.bucketFor(pkg, lib, cls, fun);
      buckets[bucket] = (buckets[bucket] ?? 0) + sz;
    });

    return Histogram._(bucketing, buckets);
  }
}