GTS 中testPersistentProcessMemory fail 详解

news2024/12/23 0:12:01

0. 前言

GTS 在测试 case armeabi-v7a GtsMemoryTestCases 的时候出现下面异常,本文总结一下。

com.google.android.memory.gts.MemoryTest#testPersistentProcessMemory

1. error log

09-14 09:41:40.523 10182 13340 13359 E TestRunner: failed: testPersistentProcessMemory(com.google.android.memory.gts.MemoryTest)
09-14 09:41:40.523 10182 13340 13359 E TestRunner: ----- begin exception -----
09-14 09:41:40.525 10182 13340 13359 E TestRunner: java.lang.AssertionError: memory usage for persistent processes is too high: 140867 > 133120
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.Assert.fail(Assert.java:89)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.Assert.assertTrue(Assert.java:42)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at com.google.android.memory.gts.MemoryTest.testPersistentProcessMemory(MemoryTest.java:75)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at java.lang.reflect.Method.invoke(Native Method)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:148)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:142)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: 	at java.lang.Thread.run(Thread.java:923)
09-14 09:41:40.525 10182 13340 13359 E TestRunner: ----- end exception -----
09-14 09:41:40.530 10182 13340 13359 I TestRunner: finished: testPersistentProcessMemory(com.google.android.memory.gts.MemoryTest)

从log 上来看,出现了 persistent processes 使用的memory 太高了,达到了140867Kb ,而GTS 测试允许的 persistent processes memory 为 133120Kb。

E TestRunner: java.lang.AssertionError: memory usage for persistent processes is too high: 140867 > 133120

2. source code

同其他的GTS 测试,找到对应的测试case,将其反编译之后就可以查看源码: 

package com.google.android.memory.gts;

import android.app.ActivityManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.DynamicConfigDeviceSide;
import com.android.compatibility.common.util.SystemUtil;
import com.android.xts.common.util.GmsUtil;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class MemoryTest {
    private static final Pattern DEVICE_HEIGHT_PATTERN = Pattern.compile("deviceHeight=(\\d+)");
    private static final Pattern DEVICE_WIDTH_PATTERN = Pattern.compile("deviceWidth=(\\d+)");
    private static final String DUMPSYS_DISPLAY = "dumpsys display";
    private static final String DUMPSYS_MEMINFO_CMD = "dumpsys -t 30 meminfo";
    private static final String MEMORY_USAGE_HIGH_MSG = "memory usage for persistent processes is too high: %d > %d";
    private static final long ONE_MEGABYTE = 1048576;
    private static final String PERSISTENT_MEMORY_KEY_FORMAT = "max_memory_persistent_%s_%s";
    private static final String PERSISTENT_MEMORY_REGEX = "(?=([\\d,]+)K: Persistent)(?!.*Service).*";
    private ActivityManager mActivityManager;

    @Before
    public void checkGoDevice() {
        Assume.assumeTrue("Skipping MemoryTest on non-Go device", GmsUtil.isGoDevice());
        this.mActivityManager = (ActivityManager) InstrumentationRegistry.getTargetContext().getSystemService(ActivityManager.class);
    }

    @Test
    public void testPersistentProcessMemory() throws Exception {
        long memoryKb = calculatePersistentMemoryUsage();
        long maxMemoryKb = getMaxPersistentMemoryAllowed();
        boolean z = false;
        String format = String.format(MEMORY_USAGE_HIGH_MSG, new Object[]{Long.valueOf(memoryKb), Long.valueOf(maxMemoryKb)});
        if (memoryKb < maxMemoryKb) {
            z = true;
        }
        Assert.assertTrue(format, z);
    }

    private long calculatePersistentMemoryUsage() throws Exception {
        String memoryUsage = findMatch(PERSISTENT_MEMORY_REGEX, SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), DUMPSYS_MEMINFO_CMD));
        Assert.assertNotNull("Could not get meminfo total", memoryUsage);
        return Long.valueOf(memoryUsage.replaceAll("[^0-9]", "")).longValue();
    }

    private long getMaxPersistentMemoryAllowed() throws Exception {
        return getLongFromConfig(keyForDeviceBasedOnMemoryAndScreenLayoutSize());
    }

    private String findMatch(String regex, String input) {
        Matcher matcher = Pattern.compile(regex).matcher(input);
        ArrayList arrayList = new ArrayList();
        while (matcher.find()) {
            arrayList.add(matcher.group(0));
        }
        if (arrayList.isEmpty()) {
            return null;
        }
        return (String) (arrayList.size() > 1 ? arrayList.get(1) : arrayList.get(0));
    }

    private long getLongFromConfig(String key) throws Exception {
        DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide("GtsMemoryTestCases");
        Assert.assertNotNull("Unable to get key from config: " + key, dcds.getValue(key));
        return new Long(dcds.getValue(key)).longValue();
    }

    private String keyForDeviceBasedOnMemoryAndScreenLayoutSize() throws Exception {
        return String.format(PERSISTENT_MEMORY_KEY_FORMAT, new Object[]{memoryClass(), calculateScreenLayoutSize()});
    }

    private String memoryClass() throws Exception {
        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
        this.mActivityManager.getMemoryInfo(memoryInfo);
        long totalMemoryBytes = memoryInfo.totalMem;
        if (totalMemoryBytes <= 536870912) {
            return "512";
        }
        if (totalMemoryBytes <= 1073741824) {
            return "1gb";
        }
        return "2gb";
    }

    private String calculateScreenLayoutSize() throws Exception {
        Matcher matcher = DEVICE_WIDTH_PATTERN.matcher(SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), DUMPSYS_DISPLAY));
        Assert.assertTrue("deviceWidth not found", matcher.find());
        long deviceWidth = Long.valueOf(matcher.group(1)).longValue();
        matcher.usePattern(DEVICE_HEIGHT_PATTERN);
        Assert.assertTrue("deviceHeight not found", matcher.find());
        long deviceHeight = Long.valueOf(matcher.group(1)).longValue();
        long shortSide = Math.min(deviceWidth, deviceHeight);
        long longSide = Math.max(deviceWidth, deviceHeight);
        if (shortSide <= 480 && longSide <= 640) {
            return "vga";
        }
        if (shortSide <= 480 && longSide <= 854) {
            return "wvga";
        }
        if (shortSide > 540 || longSide > 960) {
            return "hd";
        }
        return "qhd";
    }
}

进入测试函数 testPersistentProcessMemory():

  • 首先通过 calculatePersistentMemoryUsage() 函数确定经过 dupmsys -t 30 meminfo 之后所有 Persistent 进程的内存,存放在变量 memoryKb 中。
  • 接着通过 getMaxPersistentMemoryAllowed() 函数,确定 GTS 允许的最大 persistent memory,存放在变量 maxMemoryKb中。
    • 主要是解析 GtsMemoryTestCases.dynamic 文件中的某一个属性值;
    • 该dynamic 中属性 key 通过函数 keyForDeviceBasedOnMemoryAndScreenLayoutSize() 获取;
    • 从 log 来看,显然解析的是 max_memory_persistent_2gb_hd 属性的值 133120
  • GTS 要求,memoryKb 不能大于等于 maxMemroyKb;

另外,需要注意的是memoryKb 是通过 Java 的Pattern 类进行正则表达式匹配:

private static final String PERSISTENT_MEMORY_REGEX = "(?=([\\d,]+)K: Persistent)(?!.*Service).*";

应该就是匹配 dumpsys meminfo 中带有 Persistent 的一行,但不包括Persistent Service 这一行。例如,

    261,364K: Persistent

但不统计:

     26,620K: Persistent Service

2.1 GtsMemroyTestCases.synamic

<dynamicConfig>
    <entry key="max_memory_persistent">
      <value>90000</value>
    </entry>
    <entry key="max_memory_persistent_512_vga">
      <value>81920</value>
    </entry>
    <entry key="max_memory_persistent_512_wvga">
      <value>87040</value>
    </entry>
    <entry key="max_memory_persistent_1gb_vga">
      <value>87040</value>
    </entry>
    <entry key="max_memory_persistent_1gb_wvga">
      <value>92160</value>
    </entry>
    <entry key="max_memory_persistent_1gb_qhd">
      <value>97280</value>
    </entry>
    <entry key="max_memory_persistent_1gb_hd">
      <value>102400</value>
    </entry>
    <entry key="max_memory_persistent_2gb_vga">
      <value>102400</value>
    </entry>
    <entry key="max_memory_persistent_2gb_wvga">
      <value>112640</value>
    </entry>
    <entry key="max_memory_persistent_2gb_qhd">
      <value>122880</value>
    </entry>
    <entry key="max_memory_persistent_2gb_hd">
      <value>133120</value>
    </entry>
</dynamicConfig>

代码中会通过 dumpsys display 解析设备的 width 和 height:

  mViewports=[DisplayViewport{type=INTERNAL, valid=true, isActive=false, displayId=0, uniqueId='local:0', physicalPort=0, orientation=0, logicalFrame=Rect(0, 0 - 720, 1650), physicalFrame=Rect(0, 0 - 720, 1650), deviceWidth=720, deviceHeight=1650}]

在函数 calculateScreenLayoutSiz() 中确定 layout size

3. 解决方案

dumpsys meminfo,确认 persistent 进程的内存使用,要求不要超过 GTS 设置的max 值

 

 

 

 

 

参考:

https://blog.csdn.net/yaomingyang/article/details/79175333

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1010307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网攻西北工业大学的美国安局人员真实身份锁定!

14日&#xff0c;《环球时报》从国家计算机病毒应急处理中心和360获悉&#xff0c;在侦办西北工业大学网络攻击案过程中&#xff0c;我方成功提取了名为“二次约会”&#xff08;Second Date&#xff09;“间谍”软件的多个样本。在多国业内伙伴通力合作下&#xff0c;现已成功…

【ELK】日志分析系统概述及部署

目录 一、ELK概述 1、ELK是什么&#xff1f; 2、ELK的组成部分 2.1 ElasticSearch &#xff08;1&#xff09;分片和副本 &#xff08;2&#xff09;es和传统数据库的区别 2.2 Kiabana 2.3 Logstash &#xff08;1&#xff09;Log Stash主要组件 2.4 可添加的其它组件 …

Opencv之区域生长和分裂

区域生长 1.基本原理 区域生长法是较为基础的一种区域分割方法 它的基本思想我说的通俗些&#xff0c;即是一开始有一个生长点&#xff08;可以一个像素也可以是一个小区域&#xff09;&#xff0c;从这个生长点开始往外扩充&#xff0c;扩充的意思就是它会把跟自己有相似特征…

Python工程师Java之路(p)Maven聚合和继承

文章目录 依赖管理依赖传递可选依赖和排除依赖 继承与聚合 依赖管理 指当前项目运行所需的jar&#xff0c;一个项目可以设置多个依赖 <!-- 设置当前项目所依赖的所有jar --> <dependencies><!-- 设置具体的依赖 --><dependency><!-- 依赖所属群组…

gmssl v2 用 dgst 命令通过 sm2 签名出的结果,在别的工具上无法验签的问题分析

结论 通过分析发现&#xff0c;导致问题的原因是&#xff1a;gmssl v2 调用的算法不是 sm2 算法。 分析详情 具体情况如下所述 在 gmssl 调用 pkey_ec_init 函数时&#xff0c;默认会把 ec_scheme 设置为 NID_secg_scheme 签名的过程中会调用 pkey_ec_sign 函数&#xff0c…

【Redis】Redis的特性和应用场景 · 数据类型 · 持久化 · 数据淘汰 · 事务 · 多机部署

【Redis】Redis常见面试题&#xff08;3&#xff09; 文章目录 【Redis】Redis常见面试题&#xff08;3&#xff09;1. 特性&应用场景1.1 Redis能实现什么功能1.2 Redis支持分布式的原理1.3 为什么Redis这么快1.4 Redis实现分布式锁1.5 Redis作为缓存 2. 数据类型2.1 Redis…

Day_14 > 指针进阶(3)> bubble函数

目录 1.回顾回调函数 2.写一个bubble_sort函数 2.1认识一下qsort函数 ​编辑2.2写bubble_sort函数 今天我们继续深入学习指针 1.回顾回调函数 我们回顾一下之前学过的回调函数 回调函数就是一个通过函数指针调用的函数 如果你把函数的指针&#xff08;地址&#xff09;…

​Qt for Python 入门¶​

本页重点介绍如何从源代码构建Qt for Python&#xff0c;如果你只想安装PySide2。 与你需要运行&#xff1a;pip pip install pyside2有关更多详细信息&#xff0c;请参阅我们的快速入门指南。此外&#xff0c;您可以 查看与项目相关的常见问题解答。 一般要求 Python&#xf…

博客系统(升级(Spring))(四)(完)基本功能(阅读,修改,添加,删除文章)(附带项目)

博客系统 (三&#xff09; 博客系统博客主页前端后端个人博客前端后端显示个人文章删除文章 修改文章前端后端提取文章修改文章 显示正文内容前端后端文章阅读量功能 添加文章前端后端 如何使用Redis项目地点&#xff1a; 博客系统 博客系统是干什么的&#xff1f; CSDN就是一…

Activity生命周期递归问题查看

这类问题一般比较难分析&#xff0c;符合以下情况的才有可能分析出来&#xff1a; 能够复现并调试有问题时的堆栈以及对应的event log TaskFragment#shouldSleepActivities 方法导致递归 There is a recursion among check for sleep and complete pause during sleeping 关…

dlib库详解及Python环境安装指南

dlib是一个开源的机器学习库&#xff0c;它包含了众多的机器学习算法&#xff0c;例如分类、回归、聚类等。此外&#xff0c;dlib还包含了众多的数据处理、模型训练等工具&#xff0c;使得其在机器学习领域被广泛应用。本文将详细介绍dlib库的基本概念、功能&#xff0c;以及如…

删除数据库

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 语法格式: drop database 数据库名称;这个命令谨慎使用,俗话说:删库跑路! 案列:删除testing数据库,并验证 mysql> show databases; -----------…

Kernel for SQL Database Recovery 21.1 Crack

SQL Server恢复工具 Kernel for SQL Database Recovery 21.1 具有针对不同 SQL Server 版本的全面恢复选项。它具有预览和选择功能来恢复精确的数据库对象。 好处 SQL 数据库恢复可为您带来多种好处。 完全恢复所有数据库组件 将损坏的 MDF/NDF 文件有效恢复到 Live SQL Serve…

HDMI 直通 ILA 调试实验

FPGA教程学习 第十四章 HDMI 直通 ILA 调试实验 文章目录 FPGA教程学习前言实验原理程序设计实验过程实验尝试总结TODO 前言 HDMI 输入直通到 HDMI 输出的显示&#xff0c;完成一个简单的 HDMI 输入输出检测。 实验原理 开发板 HDMI 输出接口芯片使用 ADV7511&#xff0c;HD…

【深度学习】 Python 和 NumPy 系列教程(廿二):Matplotlib详解:2、3d绘图类型(8)3D饼图(3D Pie Chart)

一、前言 Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年创建。它以简洁、易读的语法而闻名&#xff0c;并且具有强大的功能和广泛的应用领域。Python具有丰富的标准库和第三方库&#xff0c;可以用于开发各种类型的应用程序&#xff0c;包括Web开发、数据分…

期权交易保证金比例一般是多少?

期权交易是一种非常受欢迎的投资方式之一&#xff0c;它为期权市场带来了更为多样化和灵活化的交易形式。而其中的期权卖方保证金比例是期权交易中的一个重要指标&#xff0c;直接关系到投资者的风险与收益&#xff0c;下文介绍期权交易保证金比例一般是多少&#xff1f;本文来…

第六章 图 九、拓扑排序

一、AOV网 二、拓扑排序 删除入度为0的结点。 第一次遍历&#xff0c;入度为0的点为0和2&#xff0c;将他们加入排序序列0->2 第二次遍历&#xff0c;入度为0的点为1和4&#xff0c;将他们加入排序序列0->2->1->4 第三次遍历&#xff0c;入度为0的点为3&#xf…

【webrtc】VCMSessionInfo 合并一个可解码的帧

知乎大神的概括&#xff1a;VCMFrameBuffer 帧中包含VCMSessionInfo的处理&#xff0c;对VPX、h264(分析Nalus)的同一帧中的所有包进行过滤并进行完整帧组帧&#xff0c;用于sink给后续的解码。用于解码器的所以插入的数据都是VCMPacketframe_buffer指向一帧的起始数据地址&…

Django系列:Django简介与MTV架构体系概述

Django系列 Django简介与MTV架构体系概述 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/132890054 【介…

企业架构LNMP学习笔记43

memcached的使用&#xff1a; 命令行连接和操作&#xff1a; telnet连接使用&#xff1a; memcached默认使用启动服务占用tcp 11211端口&#xff0c;可以通过telnet进行连接使用。 安装telnet进行连接&#xff1a; 连接成功&#xff0c;敲击多次&#xff0c;如果看到error&…