likes
comments
collection
share

UME: 内存查看

作者站长头像
站长
· 阅读数 4

今天我们要看一下内存查看功能是如何实现的, 在看代码之前先看下效果是什么样的

UME: 内存查看

那么今天就主要分三个部分来看, 分别是VM Info、Memory Info及Class的内存信息,今天的主要代码都在flutter_ume_kit_perf模块中,页面代码在memory_info_page.dart中,主要逻辑都在memory_service.dart中

VM Info

通过ServiceWrapper来获取VMService

ServiceWrapper昨天应该就已经见过了,昨天也是通过这个自建类获取的VM信息从而获取的path

通过VMService拿到VM,VM中就包含Pid、CPU、Verison这些信息

VM中的信息

{
type: VM,
name: vm, 
architectureBits: 64, 
hostCPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz, 
operatingSystem: ios, 
targetCPU: x64, 
version: 2.15.0-42.0.dev (dev) (Sun Aug 22 13:00:21 2021 -0700) on "ios_x64", 
pid: 2480, 
startTime: 1636098434474, 
isolates: [
{type: @Isolate, id: isolates/290036810778119, number: 290036810778119, name: main, isSystemIsolate: false}
], 
isolateGroups: [
{type: @IsolateGroup, id: isolateGroups/12365199645329027070, number: 12365199645329027070, name: main.dart, isSystemIsolateGroup: false}
], 
systemIsolates: [
{type: @Isolate, id: isolates/2845908153139319, number: 2845908153139319, name: vm-service, isSystemIsolate: true}
], 
systemIsolateGroups: [
{type: @IsolateGroup, id: isolateGroups/5190594318708735198, number: 5190594318708735198, name: vm-service, isSystemIsolateGroup: true}
]
}

Memory Info

Memory信息同样是通过vm调用getMemoryUsage方法获取内存分配信息,将其中的members遍历筛选出bytes>0和instances>0的数据返回

{
type: MemoryUsage, 
externalUsage: 5668480, 
heapCapacity: 134545408, 
heapUsage: 115805296
}

Class的内存信息

通过vm的getAllocationProfile方法获取分配对象信息,通过members属性来获取到每个class所占用的堆信息, 并将list进行排序,将list中不是以'_'开头的name进行存储,用于显示非私有类

void _heapInfoList(List<ClassHeapStats> list) {
  allClasses = list;
  allClasses.sort((a, b) => b.accumulatedSize!.compareTo(a.accumulatedSize!));
  infoList = allClasses
      .where((element) => !element.classRef!.name!.startsWith("_"))
      .toList();
}

infolist中的ClassHeapStats存储着我们需要的信息,ClassHeapStats主要包含以下字段

classRef: 类信息

accumulatedSize: 自上次重置累加器以来为类实例分配的字节数

bytesCurrent:当前内存大小

instancesAccumulated:自上次累加器重置以来已分配的类实例数

int? instancesCurrent:当前实例数量

我们可以看到list中显示Size、Count及classname就是通过accumulatedSizeinstancesAccumulatedclassRef

info详情

info详情页里的信息主要是通过上面的classRef的id来获取到class,在class中遍历fieldsfunctions

void getClassDetailInfo(
    String classId, Function(ClsModel?) completion) async {
  Class cls = await serviceWrapper.getObject(classId) as Class;
  ClsModel? _clsModel;
  if (cls.fields != null && cls.fields!.isNotEmpty) {
    List<Property> properties = [];
    List<String> functions = [];
    cls.fields?.forEach((fieldRef) {
      Property _property = Property(fieldRef.isConst, fieldRef.isStatic,
          fieldRef.isFinal, fieldRef.declaredType!.name, fieldRef.name);
      properties.add(_property);
    });
    for (var fucRef in cls.functions!) {
      String? code;
      Obj func = await serviceWrapper.getObject(fucRef.id!);
      if (func is Func) {
        code = func.code!.name;
        if (func.code!.name!.contains("[Stub]")) {
          continue;
        }
        code = code!.replaceAll('[Unoptimized] ', '');
        code = code.replaceAll('[Optimized] ', '');
        functions.add(code);
      }
    }
    _clsModel = ClsModel(propeties: properties, functions: functions);
  }

好了今天的源码查看就到这了, 作为Flutter届的一个小学生,希望大家多多指教,有问题的地方一起讨论