Development Tip

Android에서 메모리 사용량 얻기

yourdevel 2020. 12. 10. 21:26
반응형

Android에서 메모리 사용량 얻기


Android의 CPU 또는 메모리 사용량을 얻을 수있는 API가 있습니까?

다음과 같이 하나의 코드를 시도했습니다.

package com.infostretch.mainactivity;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class CPULoad 
{
    long total = 0;
    long idle = 0;

    float usage = 0;

    public CPULoad()
    {
        readUsage();
    }

    public float getUsage()
    {
        readUsage();
        return usage;
    }

    private void readUsage()
    {
        try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/stat")), 1000);
            String load = reader.readLine();
            reader.close();

            String[] toks = load.split(" ");

            long currTotal = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4]);
            long currIdle = Long.parseLong(toks[5]);

            this.usage = (currTotal - total) * 100.0f / (currTotal - total + currIdle - idle);
            this.total = currTotal;
            this.idle = currIdle;
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }
}

이것이 올바른 방법입니까?


이 함수를 사용하여 CPU 사용량을 계산합니다. 그것이 당신을 도울 수 있기를 바랍니다.

private float readUsage() {
    try {
        RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
        String load = reader.readLine();

        String[] toks = load.split(" +");  // Split on one or more spaces

        long idle1 = Long.parseLong(toks[4]);
        long cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5])
              + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

        try {
            Thread.sleep(360);
        } catch (Exception e) {}

        reader.seek(0);
        load = reader.readLine();
        reader.close();

        toks = load.split(" +");

        long idle2 = Long.parseLong(toks[4]);
        long cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5])
            + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);

        return (float)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));

    } catch (IOException ex) {
        ex.printStackTrace();
    }

    return 0;
} 

CPU 사용량을 확인하는 쉬운 방법은 상단에 adb 도구를 사용하는 것입니다. 즉 :

adb shell top -m 10


이전 답변과 개인적인 경험을 바탕으로 CPU 사용을 모니터링하는 데 사용하는 코드는 다음과 같습니다. 이 클래스의 코드는 순수 Java로 작성되었습니다.

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Utilities available only on Linux Operating System.
 * 
 * <p>
 * A typical use is to assign a thread to CPU monitoring:
 * </p>
 * 
 * <pre>
 * &#064;Override
 * public void run() {
 *  while (CpuUtil.monitorCpu) {
 * 
 *      LinuxUtils linuxUtils = new LinuxUtils();
 * 
 *      int pid = android.os.Process.myPid();
 *      String cpuStat1 = linuxUtils.readSystemStat();
 *      String pidStat1 = linuxUtils.readProcessStat(pid);
 * 
 *      try {
 *          Thread.sleep(CPU_WINDOW);
 *      } catch (Exception e) {
 *      }
 * 
 *      String cpuStat2 = linuxUtils.readSystemStat();
 *      String pidStat2 = linuxUtils.readProcessStat(pid);
 * 
 *      float cpu = linuxUtils.getSystemCpuUsage(cpuStat1, cpuStat2);
 *      if (cpu &gt;= 0.0f) {
 *          _printLine(mOutput, &quot;total&quot;, Float.toString(cpu));
 *      }
 * 
 *      String[] toks = cpuStat1.split(&quot; &quot;);
 *      long cpu1 = linuxUtils.getSystemUptime(toks);
 * 
 *      toks = cpuStat2.split(&quot; &quot;);
 *      long cpu2 = linuxUtils.getSystemUptime(toks);
 * 
 *      cpu = linuxUtils.getProcessCpuUsage(pidStat1, pidStat2, cpu2 - cpu1);
 *      if (cpu &gt;= 0.0f) {
 *          _printLine(mOutput, &quot;&quot; + pid, Float.toString(cpu));
 *      }
 * 
 *      try {
 *          synchronized (this) {
 *              wait(CPU_REFRESH_RATE);
 *          }
 *      } catch (InterruptedException e) {
 *          e.printStackTrace();
 *          return;
 *      }
 *  }
 * 
 *  Log.i(&quot;THREAD CPU&quot;, &quot;Finishing&quot;);
 * }
 * </pre>
 */
public final class LinuxUtils {

    // Warning: there appears to be an issue with the column index with android linux:
    // it was observed that on most present devices there are actually
    // two spaces between the 'cpu' of the first column and the value of 
    // the next column with data. The thing is the index of the idle 
    // column should have been 4 and the first column with data should have index 1. 
    // The indexes defined below are coping with the double space situation.
    // If your file contains only one space then use index 1 and 4 instead of 2 and 5.
    // A better way to deal with this problem may be to use a split method 
    // not preserving blanks or compute an offset and add it to the indexes 1 and 4.

    private static final int FIRST_SYS_CPU_COLUMN_INDEX = 2;

    private static final int IDLE_SYS_CPU_COLUMN_INDEX = 5;

    /** Return the first line of /proc/stat or null if failed. */
    public String readSystemStat() {

        RandomAccessFile reader = null;
        String load = null;

        try {
            reader = new RandomAccessFile("/proc/stat", "r");
            load = reader.readLine();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            Streams.close(reader);
        }

        return load;
    }

    /**
     * Compute and return the total CPU usage, in percent.
     * 
     * @param start
     *            first content of /proc/stat. Not null.
     * @param end
     *            second content of /proc/stat. Not null.
     * @return 12.7 for a CPU usage of 12.7% or -1 if the value is not
     *         available.
     * @see {@link #readSystemStat()}
     */
    public float getSystemCpuUsage(String start, String end) {
        String[] stat = start.split("\\s");
        long idle1 = getSystemIdleTime(stat);
        long up1 = getSystemUptime(stat);

        stat = end.split("\\s");
        long idle2 = getSystemIdleTime(stat);
        long up2 = getSystemUptime(stat);

        // don't know how it is possible but we should care about zero and
        // negative values.
        float cpu = -1f;
        if (idle1 >= 0 && up1 >= 0 && idle2 >= 0 && up2 >= 0) {
            if ((up2 + idle2) > (up1 + idle1) && up2 >= up1) {
                cpu = (up2 - up1) / (float) ((up2 + idle2) - (up1 + idle1));
                cpu *= 100.0f;
            }
        }

        return cpu;
    }

    /**
     * Return the sum of uptimes read from /proc/stat.
     * 
     * @param stat
     *            see {@link #readSystemStat()}
     */
    public long getSystemUptime(String[] stat) {
        /*
         * (from man/5/proc) /proc/stat kernel/system statistics. Varies with
         * architecture. Common entries include: cpu 3357 0 4313 1362393
         * 
         * The amount of time, measured in units of USER_HZ (1/100ths of a
         * second on most architectures, use sysconf(_SC_CLK_TCK) to obtain the
         * right value), that the system spent in user mode, user mode with low
         * priority (nice), system mode, and the idle task, respectively. The
         * last value should be USER_HZ times the second entry in the uptime
         * pseudo-file.
         * 
         * In Linux 2.6 this line includes three additional columns: iowait -
         * time waiting for I/O to complete (since 2.5.41); irq - time servicing
         * interrupts (since 2.6.0-test4); softirq - time servicing softirqs
         * (since 2.6.0-test4).
         * 
         * Since Linux 2.6.11, there is an eighth column, steal - stolen time,
         * which is the time spent in other operating systems when running in a
         * virtualized environment
         * 
         * Since Linux 2.6.24, there is a ninth column, guest, which is the time
         * spent running a virtual CPU for guest operating systems under the
         * control of the Linux kernel.
         */

        // with the following algorithm, we should cope with all versions and
        // probably new ones.
        long l = 0L;

        for (int i = FIRST_SYS_CPU_COLUMN_INDEX; i < stat.length; i++) {
            if (i != IDLE_SYS_CPU_COLUMN_INDEX ) { // bypass any idle mode. There is currently only one.
                try {
                    l += Long.parseLong(stat[i]);
                } catch (NumberFormatException ex) {
                    ex.printStackTrace();
                    return -1L;
                }
            }
        }

        return l;
    }

    /**
     * Return the sum of idle times read from /proc/stat.
     * 
     * @param stat
     *            see {@link #readSystemStat()}
     */
    public long getSystemIdleTime(String[] stat) {
        try {
            return Long.parseLong(stat[IDLE_SYS_CPU_COLUMN_INDEX]);
        } catch (NumberFormatException ex) {
            ex.printStackTrace();
        }

        return -1L;
    }

    /** Return the first line of /proc/pid/stat or null if failed. */
    public String readProcessStat(int pid) {

        RandomAccessFile reader = null;
        String line = null;

        try {
            reader = new RandomAccessFile("/proc/" + pid + "/stat", "r");
            line = reader.readLine();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            Streams.close(reader);
        }

        return line;
    }

    /**
     * Compute and return the CPU usage for a process, in percent.
     * 
     * <p>
     * The parameters {@code totalCpuTime} is to be the one for the same period
     * of time delimited by {@code statStart} and {@code statEnd}.
     * </p>
     * 
     * @param start
     *            first content of /proc/pid/stat. Not null.
     * @param end
     *            second content of /proc/pid/stat. Not null.
     * @return the CPU use in percent or -1f if the stats are inverted or on
     *         error
     * @param uptime
     *            sum of user and kernel times for the entire system for the
     *            same period of time.
     * @return 12.7 for a cpu usage of 12.7% or -1 if the value is not available
     *         or an error occurred.
     * @see {@link #readProcessStat(int)}
     */
    public float getProcessCpuUsage(String start, String end, long uptime) {

        String[] stat = start.split("\\s");
        long up1 = getProcessUptime(stat);

        stat = end.split("\\s");
        long up2 = getProcessUptime(stat);

        float ret = -1f;
        if (up1 >= 0 && up2 >= up1 && uptime > 0.) {
            ret = 100.f * (up2 - up1) / (float) uptime;
        }

        return ret;
    }

    /**
     * Decode the fields of the file {@code /proc/pid/stat} and return (utime +
     * stime)
     * 
     * @param stat
     *            obtained with {@link #readProcessStat(int)}
     */
    public long getProcessUptime(String[] stat) {
        return Long.parseLong(stat[14]) + Long.parseLong(stat[15]);
    }

    /**
     * Decode the fields of the file {@code /proc/pid/stat} and return (cutime +
     * cstime)
     * 
     * @param stat
     *            obtained with {@link #readProcessStat(int)}
     */
    public long getProcessIdleTime(String[] stat) {
        return Long.parseLong(stat[16]) + Long.parseLong(stat[17]);
    }

    /**
     * Return the total CPU usage, in percent.
     * <p>
     * The call is blocking for the time specified by elapse.
     * </p>
     * 
     * @param elapse
     *            the time in milliseconds between reads.
     * @return 12.7 for a CPU usage of 12.7% or -1 if the value is not
     *         available.
     */
    public float syncGetSystemCpuUsage(long elapse) {

        String stat1 = readSystemStat();
        if (stat1 == null) {
            return -1.f;
        }

        try {
            Thread.sleep(elapse);
        } catch (Exception e) {
        }

        String stat2 = readSystemStat();
        if (stat2 == null) {
            return -1.f;
        }

        return getSystemCpuUsage(stat1, stat2);
    }

    /**
     * Return the CPU usage of a process, in percent.
     * <p>
     * The call is blocking for the time specified by elapse.
     * </p>
     * 
     * @param pid
     * @param elapse
     *            the time in milliseconds between reads.
     * @return 6.32 for a CPU usage of 6.32% or -1 if the value is not
     *         available.
     */
    public float syncGetProcessCpuUsage(int pid, long elapse) {

        String pidStat1 = readProcessStat(pid);
        String totalStat1 = readSystemStat();
        if (pidStat1 == null || totalStat1 == null) {
            return -1.f;
        }

        try {
            Thread.sleep(elapse);
        } catch (Exception e) {
            e.printStackTrace();
            return -1.f;
        }

        String pidStat2 = readProcessStat(pid);
        String totalStat2 = readSystemStat();
        if (pidStat2 == null || totalStat2 == null) {
            return -1.f;
        }

        String[] toks = totalStat1.split("\\s");
        long cpu1 = getSystemUptime(toks);

        toks = totalStat2.split("\\s");
        long cpu2 = getSystemUptime(toks);

        return getProcessCpuUsage(pidStat1, pidStat2, cpu2 - cpu1);
    }

}

이 클래스를 악용하는 방법에는 여러 가지가 있습니다. syncGetSystemCpuUsage또는 호출 할 수 syncGetProcessCpuUsage있지만 각각 호출 스레드를 차단합니다. 일반적인 문제는 현재 프로세스의 총 CPU 사용량과 CPU 사용량을 동시에 모니터링하는 것이므로 두 가지를 모두 계산하는 클래스를 설계했습니다. 해당 클래스에는 전용 스레드가 포함되어 있습니다. 출력 관리는 구현별로 다르며 사용자가 직접 코딩해야합니다.

클래스는 몇 가지 방법으로 사용자 정의 할 수 있습니다. 상수 CPU_WINDOW는 읽기의 깊이, 즉 읽기와 해당 CPU 부하 계산 사이의 밀리 초 수를 정의합니다. CPU_REFRESH_RATE각 CPU로드 측정 사이의 시간입니다. CPU_REFRESH_RATE0으로 설정하지 마십시오 . 첫 번째 읽기 후에 스레드가 일시 중단되기 때문입니다.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import android.app.Application;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import my.app.LinuxUtils;
import my.app.Streams;
import my.app.TestReport;
import my.app.Utils;

public final class CpuUtil {

    private static final int CPU_WINDOW = 1000;

    private static final int CPU_REFRESH_RATE = 100; // Warning: anything but > 0

    private static HandlerThread handlerThread;

    private static TestReport output;

    static {
        output = new TestReport();
        output.setDateFormat(Utils.getDateFormat(Utils.DATE_FORMAT_ENGLISH));
    }

    private static boolean monitorCpu;

    /**
     * Construct the class singleton. This method should be called in
     * {@link Application#onCreate()}
     * 
     * @param dir
     *            the parent directory
     * @param append
     *            mode
     */
    public static void setOutput(File dir, boolean append) {
        try {
            File file = new File(dir, "cpu.txt");
            output.setOutputStream(new FileOutputStream(file, append));
            if (!append) {
                output.println(file.getAbsolutePath());
                output.newLine(1);

                // print header
                _printLine(output, "Process", "CPU%");

                output.flush();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /** Start CPU monitoring */
    public static boolean startCpuMonitoring() {
        CpuUtil.monitorCpu = true;

        handlerThread = new HandlerThread("CPU monitoring"); //$NON-NLS-1$
        handlerThread.start();

        Handler handler = new Handler(handlerThread.getLooper());
        handler.post(new Runnable() {

            @Override
            public void run() {
                while (CpuUtil.monitorCpu) {

                    LinuxUtils linuxUtils = new LinuxUtils();

                    int pid = android.os.Process.myPid();
                    String cpuStat1 = linuxUtils.readSystemStat();
                    String pidStat1 = linuxUtils.readProcessStat(pid);

                    try {
                        Thread.sleep(CPU_WINDOW);
                    } catch (Exception e) {
                    }

                    String cpuStat2 = linuxUtils.readSystemStat();
                    String pidStat2 = linuxUtils.readProcessStat(pid);

                    float cpu = linuxUtils
                            .getSystemCpuUsage(cpuStat1, cpuStat2);
                    if (cpu >= 0.0f) {
                        _printLine(output, "total", Float.toString(cpu));
                    }

                    String[] toks = cpuStat1.split(" ");
                    long cpu1 = linuxUtils.getSystemUptime(toks);

                    toks = cpuStat2.split(" ");
                    long cpu2 = linuxUtils.getSystemUptime(toks);

                    cpu = linuxUtils.getProcessCpuUsage(pidStat1, pidStat2,
                            cpu2 - cpu1);
                    if (cpu >= 0.0f) {
                        _printLine(output, "" + pid, Float.toString(cpu));
                    }

                    try {
                        synchronized (this) {
                            wait(CPU_REFRESH_RATE);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        return;
                    }
                }

                Log.i("THREAD CPU", "Finishing");
            }

        });

        return CpuUtil.monitorCpu;
    }

    /** Stop CPU monitoring */
    public static void stopCpuMonitoring() {
        if (handlerThread != null) {
            monitorCpu = false;
            handlerThread.quit();
            handlerThread = null;
        }
    }

    /** Dispose of the object and release the resources allocated for it */
    public void dispose() {

        monitorCpu = false;

        if (output != null) {
            OutputStream os = output.getOutputStream();
            if (os != null) {
                Streams.close(os);
                output.setOutputStream(null);
            }

            output = null;
        }
    }

    private static void _printLine(TestReport output, String process, String cpu) {
        output.stampln(process + ";" + cpu);
    }

}

Since the OP asked about CPU usage AND memory usage (accepted answer only shows technique to get cpu usage), I'd like to recommend the ActivityManager class and specifically the accepted answer from this question: How to get current memory usage in android?


Check the Debug class. http://developer.android.com/reference/android/os/Debug.html i.e. Debug.getNativeHeapAllocatedSize()

It has methods to get the used native heap, which is i.e. used by external bitmaps in your app. For the heap that the app is using internally, you can see that in the DDMS tool that comes with the Android SDK and is also available via Eclipse.

The native heap + the heap as indicated in the DDMS make up the total heap that your app is allocating.

For CPU usage I'm not sure if there's anything available via API/SDK.


enter the android terminal and then you can type the following commands :dumpsys cpuinfo

shell@android:/ $ dumpsys cpuinfo                                              
Load: 0.8 / 0.75 / 1.15
CPU usage from 69286ms to 9283ms ago with 99% awake:
  47% 1118/com.wxg.sodproject: 12% user + 35% kernel
  1.6% 1225/android.process.media: 1% user + 0.6% kernel
  1.3% 263/mpdecision: 0.1% user + 1.2% kernel
  0.1% 32747/kworker/u:1: 0% user + 0.1% kernel
  0.1% 883/com.android.systemui: 0.1% user + 0% kernel
  0.1% 521/system_server: 0.1% user + 0% kernel / faults: 14 minor
  0.1% 1826/com.quicinc.trepn: 0.1% user + 0% kernel
  0.1% 2462/kworker/0:2: 0.1% user + 0% kernel
  0.1% 32649/kworker/0:0: 0% user + 0.1% kernel
  0% 118/mmcqd/0: 0% user + 0% kernel
  0% 179/surfaceflinger: 0% user + 0% kernel
  0% 46/kinteractiveup: 0% user + 0% kernel
  0% 141/jbd2/mmcblk0p26: 0% user + 0% kernel
  0% 239/sdcard: 0% user + 0% kernel
  0% 1171/com.xiaomi.channel:pushservice: 0% user + 0% kernel / faults: 1 minor
  0% 1207/com.xiaomi.channel: 0% user + 0% kernel / faults: 1 minor
  0% 32705/kworker/0:1: 0% user + 0% kernel
12% TOTAL: 3.2% user + 9.4% kernel + 0% iowait

참고URL : https://stackoverflow.com/questions/3118234/get-memory-usage-in-android

반응형