summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-09-11 17:33:14 -0700
committerJeff Sharkey <jsharkey@android.com>2011-09-12 16:13:20 -0700
commit69b0f63af2e3babc2e9f048c4682032a0c17d9d0 (patch)
treebd8a475fbaa2ca320f0cafaea40ba16c54111074 /core
parent1d50a2c0682926f783f9acab5c4bdeca1d3cb9cd (diff)
downloadframeworks_base-69b0f63af2e3babc2e9f048c4682032a0c17d9d0.zip
frameworks_base-69b0f63af2e3babc2e9f048c4682032a0c17d9d0.tar.gz
frameworks_base-69b0f63af2e3babc2e9f048c4682032a0c17d9d0.tar.bz2
Data usage structure optimizations.
Driven by traceview hotspots found in Settings UI. Change-Id: I614a049523c526b7fcd12fffdf53a3e4723623e4
Diffstat (limited to 'core')
-rw-r--r--core/java/android/net/NetworkStatsHistory.java45
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java48
2 files changed, 89 insertions, 4 deletions
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index d07d899..d8ac31f 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -29,6 +29,7 @@ import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.MathUtils;
import java.io.CharArrayWriter;
import java.io.DataInputStream;
@@ -207,6 +208,34 @@ public class NetworkStatsHistory implements Parcelable {
}
/**
+ * Return index of bucket that contains or is immediately before the
+ * requested time.
+ */
+ public int getIndexBefore(long time) {
+ int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
+ if (index < 0) {
+ index = (~index) - 1;
+ } else {
+ index -= 1;
+ }
+ return MathUtils.constrain(index, 0, bucketCount - 1);
+ }
+
+ /**
+ * Return index of bucket that contains or is immediately after the
+ * requested time.
+ */
+ public int getIndexAfter(long time) {
+ int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
+ if (index < 0) {
+ index = ~index;
+ } else {
+ index += 1;
+ }
+ return MathUtils.constrain(index, 0, bucketCount - 1);
+ }
+
+ /**
* Return specific stats entry.
*/
public Entry getValues(int i, Entry recycle) {
@@ -247,7 +276,8 @@ public class NetworkStatsHistory implements Parcelable {
// distribute data usage into buckets
long duration = end - start;
- for (int i = bucketCount - 1; i >= 0; i--) {
+ final int startIndex = getIndexAfter(end);
+ for (int i = startIndex; i >= 0; i--) {
final long curStart = bucketStart[i];
final long curEnd = curStart + bucketDuration;
@@ -406,7 +436,8 @@ public class NetworkStatsHistory implements Parcelable {
entry.txPackets = txPackets != null ? 0 : UNKNOWN;
entry.operations = operations != null ? 0 : UNKNOWN;
- for (int i = bucketCount - 1; i >= 0; i--) {
+ final int startIndex = getIndexAfter(end);
+ for (int i = startIndex; i >= 0; i--) {
final long curStart = bucketStart[i];
final long curEnd = curStart + bucketDuration;
@@ -417,8 +448,14 @@ public class NetworkStatsHistory implements Parcelable {
// include full value for active buckets, otherwise only fractional
final boolean activeBucket = curStart < now && curEnd > now;
- final long overlap = activeBucket ? bucketDuration
- : Math.min(curEnd, end) - Math.max(curStart, start);
+ final long overlap;
+ if (activeBucket) {
+ overlap = bucketDuration;
+ } else {
+ final long overlapEnd = curEnd < end ? curEnd : end;
+ final long overlapStart = curStart > start ? curStart : start;
+ overlap = overlapEnd - overlapStart;
+ }
if (overlap <= 0) continue;
// integer math each time is faster than floating point
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index b888d9a..e1db073 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -407,6 +407,54 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertEquals(Long.MAX_VALUE - 40, performVarLong(Long.MAX_VALUE - 40));
}
+ public void testIndexBeforeAfter() throws Exception {
+ final long BUCKET_SIZE = HOUR_IN_MILLIS;
+ stats = new NetworkStatsHistory(BUCKET_SIZE);
+
+ final long FIRST_START = TEST_START;
+ final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS);
+ final long SECOND_START = TEST_START + WEEK_IN_MILLIS;
+ final long SECOND_END = SECOND_START + HOUR_IN_MILLIS;
+ final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS);
+ final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS);
+
+ stats.recordData(FIRST_START, FIRST_END,
+ new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
+ stats.recordData(SECOND_START, SECOND_END,
+ new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
+ stats.recordData(THIRD_START, THIRD_END,
+ new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
+
+ // should have buckets: 2+1+2
+ assertEquals(5, stats.size());
+
+ assertIndexBeforeAfter(stats, 0, 0, Long.MIN_VALUE);
+ assertIndexBeforeAfter(stats, 0, 1, FIRST_START);
+ assertIndexBeforeAfter(stats, 0, 1, FIRST_START + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 0, 2, FIRST_START + HOUR_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 1, 2, FIRST_START + HOUR_IN_MILLIS + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 1, 2, FIRST_END - MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 1, 2, FIRST_END);
+ assertIndexBeforeAfter(stats, 1, 2, FIRST_END + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 1, 2, SECOND_START - MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 1, 3, SECOND_START);
+ assertIndexBeforeAfter(stats, 2, 3, SECOND_END);
+ assertIndexBeforeAfter(stats, 2, 3, SECOND_END + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 2, 3, THIRD_START - MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 2, 4, THIRD_START);
+ assertIndexBeforeAfter(stats, 3, 4, THIRD_START + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 3, 4, THIRD_START + HOUR_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 4, 4, THIRD_END);
+ assertIndexBeforeAfter(stats, 4, 4, THIRD_END + MINUTE_IN_MILLIS);
+ assertIndexBeforeAfter(stats, 4, 4, Long.MAX_VALUE);
+ }
+
+ private static void assertIndexBeforeAfter(
+ NetworkStatsHistory stats, int before, int after, long time) {
+ assertEquals("unexpected before", before, stats.getIndexBefore(time));
+ assertEquals("unexpected after", after, stats.getIndexAfter(time));
+ }
+
private static long performVarLong(long before) throws Exception {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
writeVarLong(new DataOutputStream(out), before);