From be68c7c5c70cb875cbc42c1e0ae22f04d876180b Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 27 Feb 2012 18:08:01 -0800 Subject: [PATCH] Move NetworkStatsFactory to faster ProcFileReader. Less GC overhead, and about 8x faster parse times. Verified that tests pass. Change-Id: Iff1d374f36103395a193176a88a57eebffa93c56 --- .../internal/net/NetworkStatsFactory.java | 85 ++++--------------- 1 file changed, 15 insertions(+), 70 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 4e3d9650f8..ccd27632b9 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -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 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 values = Lists.newArrayList(); - final HashMap 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 parsed, String key) { - final String value = parsed.get(key); - return value != null ? Integer.parseInt(value) : 0; - } - - @Deprecated - private static long getParsedLong(HashMap 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 keys, ArrayList values, HashMap 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.