Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d29a306 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Move NetworkStatsFactory to faster ProcFileReader.

Less GC overhead, and about 8x faster parse times.  Verified that
tests pass.

Change-Id: Iff1d374f36103395a193176a88a57eebffa93c56
parent 453dafa6
Loading
Loading
Loading
Loading
+15 −70
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.util.Slog;

import com.android.internal.util.ProcFileReader;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;

import java.io.BufferedReader;
@@ -37,7 +36,6 @@ import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.StringTokenizer;

@@ -63,22 +61,6 @@ public class NetworkStatsFactory {
    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
    private final File mStatsXtUid;

    /** {@link #mStatsXtUid} and {@link #mStatsXtIfaceAll} headers. */
    private static final String KEY_IDX = "idx";
    private static final String KEY_IFACE = "iface";
    private static final String KEY_ACTIVE = "active";
    private static final String KEY_UID = "uid_tag_int";
    private static final String KEY_COUNTER_SET = "cnt_set";
    private static final String KEY_TAG_HEX = "acct_tag_hex";
    private static final String KEY_SNAP_RX_BYTES = "snap_rx_bytes";
    private static final String KEY_SNAP_RX_PACKETS = "snap_rx_packets";
    private static final String KEY_SNAP_TX_BYTES = "snap_tx_bytes";
    private static final String KEY_SNAP_TX_PACKETS = "snap_tx_packets";
    private static final String KEY_RX_BYTES = "rx_bytes";
    private static final String KEY_RX_PACKETS = "rx_packets";
    private static final String KEY_TX_BYTES = "tx_bytes";
    private static final String KEY_TX_PACKETS = "tx_packets";

    public NetworkStatsFactory() {
        this(new File("/proc/"));
    }
@@ -112,44 +94,34 @@ public class NetworkStatsFactory {
        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
        final NetworkStats.Entry entry = new NetworkStats.Entry();

        // TODO: transition to ProcFileReader
        // TODO: read directly from proc once headers are added
        final ArrayList<String> keys = Lists.newArrayList(KEY_IFACE, KEY_ACTIVE, KEY_SNAP_RX_BYTES,
                KEY_SNAP_RX_PACKETS, KEY_SNAP_TX_BYTES, KEY_SNAP_TX_PACKETS, KEY_RX_BYTES,
                KEY_RX_PACKETS, KEY_TX_BYTES, KEY_TX_PACKETS);
        final ArrayList<String> values = Lists.newArrayList();
        final HashMap<String, String> parsed = Maps.newHashMap();

        BufferedReader reader = null;
        ProcFileReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(mStatsXtIfaceAll));
            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceAll));

            String line;
            while ((line = reader.readLine()) != null) {
                splitLine(line, values);
                parseLine(keys, values, parsed);

                entry.iface = parsed.get(KEY_IFACE);
            while (reader.hasMoreData()) {
                entry.iface = reader.nextString();
                entry.uid = UID_ALL;
                entry.set = SET_DEFAULT;
                entry.tag = TAG_NONE;

                final boolean active = reader.nextInt() != 0;

                // always include snapshot values
                entry.rxBytes = getParsedLong(parsed, KEY_SNAP_RX_BYTES);
                entry.rxPackets = getParsedLong(parsed, KEY_SNAP_RX_PACKETS);
                entry.txBytes = getParsedLong(parsed, KEY_SNAP_TX_BYTES);
                entry.txPackets = getParsedLong(parsed, KEY_SNAP_TX_PACKETS);
                entry.rxBytes = reader.nextLong();
                entry.rxPackets = reader.nextLong();
                entry.txBytes = reader.nextLong();
                entry.txPackets = reader.nextLong();

                // fold in active numbers, but only when active
                final boolean active = getParsedInt(parsed, KEY_ACTIVE) != 0;
                if (active) {
                    entry.rxBytes += getParsedLong(parsed, KEY_RX_BYTES);
                    entry.rxPackets += getParsedLong(parsed, KEY_RX_PACKETS);
                    entry.txBytes += getParsedLong(parsed, KEY_TX_BYTES);
                    entry.txPackets += getParsedLong(parsed, KEY_TX_PACKETS);
                    entry.rxBytes += reader.nextLong();
                    entry.rxPackets += reader.nextLong();
                    entry.txBytes += reader.nextLong();
                    entry.txPackets += reader.nextLong();
                }

                stats.addValues(entry);
                reader.finishLine();
            }
        } catch (NullPointerException e) {
            throw new IllegalStateException("problem parsing stats: " + e);
@@ -315,18 +287,6 @@ public class NetworkStatsFactory {
        return stats;
    }

    @Deprecated
    private static int getParsedInt(HashMap<String, String> parsed, String key) {
        final String value = parsed.get(key);
        return value != null ? Integer.parseInt(value) : 0;
    }

    @Deprecated
    private static long getParsedLong(HashMap<String, String> parsed, String key) {
        final String value = parsed.get(key);
        return value != null ? Long.parseLong(value) : 0;
    }

    /**
     * Split given line into {@link ArrayList}.
     */
@@ -340,21 +300,6 @@ public class NetworkStatsFactory {
        }
    }

    /**
     * Zip the two given {@link ArrayList} as key and value pairs into
     * {@link HashMap}.
     */
    @Deprecated
    private static void parseLine(
            ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
        outParsed.clear();

        final int size = Math.min(keys.size(), values.size());
        for (int i = 0; i < size; i++) {
            outParsed.put(keys.get(i), values.get(i));
        }
    }

    /**
     * Utility method to read a single plain-text {@link Long} from the given
     * {@link File}, usually from a {@code /proc/} filesystem.