Data usage buckets active time, parsing ISE.

When recording data usage, measure the actual active time, since
buckets can be quite long.  Offer incrementOperationCount() version
that reads thread stats tag for caller.  Rethrow any NPE as ISE
during stats parsing, which callers already handle.

Bug: 5171812, 5184508, 5180659
Change-Id: I6da80ccc0162be68bee279529e3a23b6f98ebd87
This commit is contained in:
Jeff Sharkey
2011-08-24 15:42:09 -07:00
parent 93db945091
commit 60ca02379f
2 changed files with 42 additions and 10 deletions

View File

@@ -53,18 +53,21 @@ import java.util.Random;
public class NetworkStatsHistory implements Parcelable { public class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1; private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PACKETS = 2; private static final int VERSION_ADD_PACKETS = 2;
private static final int VERSION_ADD_ACTIVE = 3;
public static final int FIELD_RX_BYTES = 0x01; public static final int FIELD_ACTIVE_TIME = 0x01;
public static final int FIELD_RX_PACKETS = 0x02; public static final int FIELD_RX_BYTES = 0x02;
public static final int FIELD_TX_BYTES = 0x04; public static final int FIELD_RX_PACKETS = 0x04;
public static final int FIELD_TX_PACKETS = 0x08; public static final int FIELD_TX_BYTES = 0x08;
public static final int FIELD_OPERATIONS = 0x10; public static final int FIELD_TX_PACKETS = 0x10;
public static final int FIELD_OPERATIONS = 0x20;
public static final int FIELD_ALL = 0xFFFFFFFF; public static final int FIELD_ALL = 0xFFFFFFFF;
private long bucketDuration; private long bucketDuration;
private int bucketCount; private int bucketCount;
private long[] bucketStart; private long[] bucketStart;
private long[] activeTime;
private long[] rxBytes; private long[] rxBytes;
private long[] rxPackets; private long[] rxPackets;
private long[] txBytes; private long[] txBytes;
@@ -74,8 +77,9 @@ public class NetworkStatsHistory implements Parcelable {
public static class Entry { public static class Entry {
public static final long UNKNOWN = -1; public static final long UNKNOWN = -1;
public long bucketStart;
public long bucketDuration; public long bucketDuration;
public long bucketStart;
public long activeTime;
public long rxBytes; public long rxBytes;
public long rxPackets; public long rxPackets;
public long txBytes; public long txBytes;
@@ -94,6 +98,7 @@ public class NetworkStatsHistory implements Parcelable {
public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) { public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
this.bucketDuration = bucketDuration; this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize]; bucketStart = new long[initialSize];
if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize]; if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize]; if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize]; if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
@@ -105,6 +110,7 @@ public class NetworkStatsHistory implements Parcelable {
public NetworkStatsHistory(Parcel in) { public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong(); bucketDuration = in.readLong();
bucketStart = readLongArray(in); bucketStart = readLongArray(in);
activeTime = readLongArray(in);
rxBytes = readLongArray(in); rxBytes = readLongArray(in);
rxPackets = readLongArray(in); rxPackets = readLongArray(in);
txBytes = readLongArray(in); txBytes = readLongArray(in);
@@ -117,6 +123,7 @@ public class NetworkStatsHistory implements Parcelable {
public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) {
out.writeLong(bucketDuration); out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount); writeLongArray(out, bucketStart, bucketCount);
writeLongArray(out, activeTime, bucketCount);
writeLongArray(out, rxBytes, bucketCount); writeLongArray(out, rxBytes, bucketCount);
writeLongArray(out, rxPackets, bucketCount); writeLongArray(out, rxPackets, bucketCount);
writeLongArray(out, txBytes, bucketCount); writeLongArray(out, txBytes, bucketCount);
@@ -138,9 +145,12 @@ public class NetworkStatsHistory implements Parcelable {
bucketCount = bucketStart.length; bucketCount = bucketStart.length;
break; break;
} }
case VERSION_ADD_PACKETS: { case VERSION_ADD_PACKETS:
case VERSION_ADD_ACTIVE: {
bucketDuration = in.readLong(); bucketDuration = in.readLong();
bucketStart = readVarLongArray(in); bucketStart = readVarLongArray(in);
activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
: new long[bucketStart.length];
rxBytes = readVarLongArray(in); rxBytes = readVarLongArray(in);
rxPackets = readVarLongArray(in); rxPackets = readVarLongArray(in);
txBytes = readVarLongArray(in); txBytes = readVarLongArray(in);
@@ -156,9 +166,10 @@ public class NetworkStatsHistory implements Parcelable {
} }
public void writeToStream(DataOutputStream out) throws IOException { public void writeToStream(DataOutputStream out) throws IOException {
out.writeInt(VERSION_ADD_PACKETS); out.writeInt(VERSION_ADD_ACTIVE);
out.writeLong(bucketDuration); out.writeLong(bucketDuration);
writeVarLongArray(out, bucketStart, bucketCount); writeVarLongArray(out, bucketStart, bucketCount);
writeVarLongArray(out, activeTime, bucketCount);
writeVarLongArray(out, rxBytes, bucketCount); writeVarLongArray(out, rxBytes, bucketCount);
writeVarLongArray(out, rxPackets, bucketCount); writeVarLongArray(out, rxPackets, bucketCount);
writeVarLongArray(out, txBytes, bucketCount); writeVarLongArray(out, txBytes, bucketCount);
@@ -202,6 +213,7 @@ public class NetworkStatsHistory implements Parcelable {
final Entry entry = recycle != null ? recycle : new Entry(); final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketStart = bucketStart[i]; entry.bucketStart = bucketStart[i];
entry.bucketDuration = bucketDuration; entry.bucketDuration = bucketDuration;
entry.activeTime = getLong(activeTime, i, UNKNOWN);
entry.rxBytes = getLong(rxBytes, i, UNKNOWN); entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
entry.rxPackets = getLong(rxPackets, i, UNKNOWN); entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
entry.txBytes = getLong(txBytes, i, UNKNOWN); entry.txBytes = getLong(txBytes, i, UNKNOWN);
@@ -252,8 +264,9 @@ public class NetworkStatsHistory implements Parcelable {
final long fracRxPackets = entry.rxPackets * overlap / duration; final long fracRxPackets = entry.rxPackets * overlap / duration;
final long fracTxBytes = entry.txBytes * overlap / duration; final long fracTxBytes = entry.txBytes * overlap / duration;
final long fracTxPackets = entry.txPackets * overlap / duration; final long fracTxPackets = entry.txPackets * overlap / duration;
final int fracOperations = (int) (entry.operations * overlap / duration); final long fracOperations = entry.operations * overlap / duration;
addLong(activeTime, i, overlap);
addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes; addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes;
addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets; addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets;
addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes; addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes;
@@ -311,6 +324,7 @@ public class NetworkStatsHistory implements Parcelable {
if (bucketCount >= bucketStart.length) { if (bucketCount >= bucketStart.length) {
final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
bucketStart = Arrays.copyOf(bucketStart, newLength); bucketStart = Arrays.copyOf(bucketStart, newLength);
if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength); if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength); if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength); if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
@@ -324,6 +338,7 @@ public class NetworkStatsHistory implements Parcelable {
final int length = bucketCount - index; final int length = bucketCount - index;
System.arraycopy(bucketStart, index, bucketStart, dstPos, length); System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length); if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length); if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length); if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
@@ -332,6 +347,7 @@ public class NetworkStatsHistory implements Parcelable {
} }
bucketStart[index] = start; bucketStart[index] = start;
setLong(activeTime, index, 0L);
setLong(rxBytes, index, 0L); setLong(rxBytes, index, 0L);
setLong(rxPackets, index, 0L); setLong(rxPackets, index, 0L);
setLong(txBytes, index, 0L); setLong(txBytes, index, 0L);
@@ -357,6 +373,7 @@ public class NetworkStatsHistory implements Parcelable {
if (i > 0) { if (i > 0) {
final int length = bucketStart.length; final int length = bucketStart.length;
bucketStart = Arrays.copyOfRange(bucketStart, i, length); bucketStart = Arrays.copyOfRange(bucketStart, i, length);
if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length); if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length); if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length); if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
@@ -380,8 +397,9 @@ public class NetworkStatsHistory implements Parcelable {
*/ */
public Entry getValues(long start, long end, long now, Entry recycle) { public Entry getValues(long start, long end, long now, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry(); final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketStart = start;
entry.bucketDuration = end - start; entry.bucketDuration = end - start;
entry.bucketStart = start;
entry.activeTime = activeTime != null ? 0 : UNKNOWN;
entry.rxBytes = rxBytes != null ? 0 : UNKNOWN; entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
entry.rxPackets = rxPackets != null ? 0 : UNKNOWN; entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
entry.txBytes = txBytes != null ? 0 : UNKNOWN; entry.txBytes = txBytes != null ? 0 : UNKNOWN;
@@ -404,6 +422,7 @@ public class NetworkStatsHistory implements Parcelable {
if (overlap <= 0) continue; if (overlap <= 0) continue;
// integer math each time is faster than floating point // integer math each time is faster than floating point
if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration;
if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration; if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration; if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration; if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
@@ -463,6 +482,7 @@ public class NetworkStatsHistory implements Parcelable {
for (int i = start; i < bucketCount; i++) { for (int i = start; i < bucketCount; i++) {
pw.print(prefix); pw.print(prefix);
pw.print(" bucketStart="); pw.print(bucketStart[i]); pw.print(" bucketStart="); pw.print(bucketStart[i]);
if (activeTime != null) pw.print(" activeTime="); pw.print(activeTime[i]);
if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]); if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]);
if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]); if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]);
if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]); if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]);

View File

@@ -197,6 +197,18 @@ public class TrafficStats {
} }
} }
/**
* Increment count of network operations performed under the accounting tag
* currently active on the calling thread. This can be used to derive
* bytes-per-operation.
*
* @param operationCount Number of operations to increment count by.
*/
public static void incrementOperationCount(int operationCount) {
final int tag = getThreadStatsTag();
incrementOperationCount(tag, operationCount);
}
/** /**
* Increment count of network operations performed under the given * Increment count of network operations performed under the given
* accounting tag. This can be used to derive bytes-per-operation. * accounting tag. This can be used to derive bytes-per-operation.