Ausführliche Erklärung des testPersistentProcessMemory-Fehlers in GTS

0. Vorwort

GTS ist beim Testen des Falls armeabi-v7a GtsMemoryTestCases auf die folgende Ausnahme gestoßen. Dieser Artikel fasst sie zusammen.

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

1. Fehlerprotokoll

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)

Aus dem Protokoll geht hervor, dass der von persistenten Prozessen verwendete Speicher zu hoch ist und 140.867 KB erreicht, während der zulässige Speicher für persistente Prozesse im GTS-Test 133.120 KB beträgt.

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

2. Quellcode

Suchen Sie wie bei anderen GTS-Tests den entsprechenden Testfall und dekompilieren Sie ihn, um den Quellcode anzuzeigen: 

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";
    }
}

Geben Sie die Testfunktion testPersistentProcessMemory() ein:

  • Bestimmen Sie zunächst den Speicher aller persistenten Prozesse nach „dupmsys -t 30 meminfo“ mithilfe  der Funktion „calculatePersistentMemoryUsage()“ und speichern Sie ihn in der Variablen „memoryKb“.
  • Verwenden Sie dann die Funktion getMaxPersistentMemoryAllowed(), um den von GTS maximal zulässigen persistenten Speicher zu ermitteln und ihn in der Variablen maxMemoryKb zu speichern.
    • Hauptsächlich zum Parsen  eines bestimmten Attributwerts in der Datei GtsMemoryTestCases.dynamic .
    • Der dynamische Attributschlüssel wird über die Funktion  keyForDeviceBasedOnMemoryAndScreenLayoutSize() abgerufen ;
    • Aus dem Protokoll geht hervor, dass  der Wert des Attributs max_memory_persistent_2gb_hd analysiert wurde : 133120 ;
  • GTS erfordert, dass „memoryKb“ nicht größer oder gleich „maxMemroyKb“ sein darf.

Darüber hinaus ist zu beachten, dass MemoryKb den Abgleich regulärer Ausdrücke über die Pattern-Klasse von Java durchführt:

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

Es sollte mit der Zeile „Persistent“ in dumpsys meminfo übereinstimmen, enthält jedoch nicht die Zeile „Persistent Service“. Zum Beispiel,

    261,364K: Persistent

Aber keine Statistik:

     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>

Im Code werden die Breite und Höhe des Geräts über die dumpsys-Anzeige analysiert:

  mViewports = [DisplayViewport PhysicalFrame=Rect(0, 0 - 720, 1650), DeviceWidth =720, DeviceHeight =1650}]

Bestimmen Sie die Layoutgröße in der Funktion  berechneScreenLayoutSiz()

3. Lösung

dumpsys meminfo, bestätigen Sie die Speichernutzung des persistenten Prozesses. Der von GTS festgelegte Maximalwert darf nicht überschritten werden.

Darüber hinaus wird zu Beginn des Fallgesprächs bestätigt, ob es sich um ein GO-Gerät handelt:

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

Dieser Fall wird nur unter GO-Gerät aufgerufen. Wenn es sich nicht um ein GO-Gerät handelt, wird es als ASSUMPTION_FAILURE betrachtet und dieser Fall übersprungen und zur Laufzeit gedruckt:

9-22 10:57:49 I/ModuleListener: [1/1] caab02bd com.google.android.memory.gts.MemoryTest#testPersistentProcessMemory ASSUMPTION_FAILURE: org.junit.AssumptionViolatedException: Skipping MemoryTest on non-Go device
	at org.junit.Assume.assumeTrue(Assume.java:68)
	at com.google.android.memory.gts.MemoryTest.checkGoDevice(MemoryTest.java:62)
	at java.lang.reflect.Method.invoke(Native Method)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:76)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.-$$Nest$mrunChildren(Unknown Source:0)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:111)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.-$$Nest$mrunChildren(Unknown Source:0)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:67)
	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:58)
	at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:445)
	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)

 

 

Referenz:

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

Ich denke du magst

Origin blog.csdn.net/jingerppp/article/details/132882587
Empfohlen
Rangfolge