Loading services/backup/java/com/android/server/backup/transport/TransportStats.java +33 −33 Original line number Diff line number Diff line Loading @@ -32,9 +32,12 @@ public class TransportStats { void registerConnectionTime(ComponentName transportComponent, long timeMs) { synchronized (mStatsLock) { mTransportStats .computeIfAbsent(transportComponent, name -> new Stats()) .register(timeMs); Stats stats = mTransportStats.get(transportComponent); if (stats == null) { stats = new Stats(); mTransportStats.put(transportComponent, stats); } stats.register(timeMs); } } Loading Loading @@ -71,52 +74,49 @@ public class TransportStats { private static void dumpStats(PrintWriter pw, String prefix, Stats stats) { pw.println( String.format( Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.mAverage)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.mMax)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.mMin)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.mN)); Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.average)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.max)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.min)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.n)); } public static final class Stats { public static Stats merge(Stats a, Stats b) { return new Stats( a.mN + b.mN, (a.mAverage * a.mN + b.mAverage * b.mN) / (a.mN + b.mN), Math.max(a.mMax, b.mMax), Math.min(a.mMin, b.mMin)); a.n + b.n, (a.average * a.n + b.average * b.n) / (a.n + b.n), Math.max(a.max, b.max), Math.min(a.min, b.min)); } public int mN; public double mAverage; public long mMax; public long mMin; public int n; public double average; public long max; public long min; public Stats() { mN = 0; mAverage = 0; mMax = 0; mMin = Long.MAX_VALUE; n = 0; average = 0; max = 0; min = Long.MAX_VALUE; } private Stats(Stats original) { mN = original.mN; mAverage = original.mAverage; mMax = original.mMax; mMin = original.mMin; private Stats(int n, double average, long max, long min) { this.n = n; this.average = average; this.max = max; this.min = min; } private Stats(int n, double average, long max, long min) { mN = n; mAverage = average; mMax = max; mMin = min; private Stats(Stats original) { this(original.n, original.average, original.max, original.min); } private void register(long sample) { mAverage = (mAverage * mN + sample) / (mN + 1); mN++; mMax = Math.max(mMax, sample); mMin = Math.min(mMin, sample); average = (average * n + sample) / (n + 1); n++; max = Math.max(max, sample); min = Math.min(min, sample); } } } services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.backup.transport; import static com.android.server.backup.testing.TransportData.backupTransport; import static com.android.server.backup.testing.TransportData.d2dTransport; import static com.google.common.truth.Truth.assertThat; import android.content.ComponentName; import android.platform.test.annotations.Presubmit; import com.android.server.backup.transport.TransportStats.Stats; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) @SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class TransportStatsTest { private static final double TOLERANCE = 0.0001; private TransportStats mTransportStats; private ComponentName mTransportComponent1; private ComponentName mTransportComponent2; @Before public void setUp() throws Exception { mTransportStats = new TransportStats(); mTransportComponent1 = backupTransport().getTransportComponent(); mTransportComponent2 = d2dTransport().getTransportComponent(); } @Test public void testRegisterConnectionTime() { mTransportStats.registerConnectionTime(mTransportComponent1, 50L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(50); assertThat(stats.max).isEqualTo(50L); assertThat(stats.min).isEqualTo(50L); assertThat(stats.n).isEqualTo(1); } @Test public void testRegisterConnectionTime_whenHasAlreadyOneSample() { mTransportStats.registerConnectionTime(mTransportComponent1, 50L); mTransportStats.registerConnectionTime(mTransportComponent1, 100L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(75); assertThat(stats.max).isEqualTo(100L); assertThat(stats.min).isEqualTo(50L); assertThat(stats.n).isEqualTo(2); } @Test public void testGetStatsForTransport() { mTransportStats.registerConnectionTime(mTransportComponent1, 10L); mTransportStats.registerConnectionTime(mTransportComponent2, 20L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(10); assertThat(stats.max).isEqualTo(10L); assertThat(stats.min).isEqualTo(10L); assertThat(stats.n).isEqualTo(1); } @Test public void testMerge() { mTransportStats.registerConnectionTime(mTransportComponent1, 10L); mTransportStats.registerConnectionTime(mTransportComponent2, 20L); Stats stats1 = mTransportStats.getStatsForTransport(mTransportComponent1); Stats stats2 = mTransportStats.getStatsForTransport(mTransportComponent2); Stats stats = Stats.merge(stats1, stats2); assertThat(stats.average).isWithin(TOLERANCE).of(15); assertThat(stats.max).isEqualTo(20L); assertThat(stats.min).isEqualTo(10L); assertThat(stats.n).isEqualTo(2); } } Loading
services/backup/java/com/android/server/backup/transport/TransportStats.java +33 −33 Original line number Diff line number Diff line Loading @@ -32,9 +32,12 @@ public class TransportStats { void registerConnectionTime(ComponentName transportComponent, long timeMs) { synchronized (mStatsLock) { mTransportStats .computeIfAbsent(transportComponent, name -> new Stats()) .register(timeMs); Stats stats = mTransportStats.get(transportComponent); if (stats == null) { stats = new Stats(); mTransportStats.put(transportComponent, stats); } stats.register(timeMs); } } Loading Loading @@ -71,52 +74,49 @@ public class TransportStats { private static void dumpStats(PrintWriter pw, String prefix, Stats stats) { pw.println( String.format( Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.mAverage)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.mMax)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.mMin)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.mN)); Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.average)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.max)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.min)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.n)); } public static final class Stats { public static Stats merge(Stats a, Stats b) { return new Stats( a.mN + b.mN, (a.mAverage * a.mN + b.mAverage * b.mN) / (a.mN + b.mN), Math.max(a.mMax, b.mMax), Math.min(a.mMin, b.mMin)); a.n + b.n, (a.average * a.n + b.average * b.n) / (a.n + b.n), Math.max(a.max, b.max), Math.min(a.min, b.min)); } public int mN; public double mAverage; public long mMax; public long mMin; public int n; public double average; public long max; public long min; public Stats() { mN = 0; mAverage = 0; mMax = 0; mMin = Long.MAX_VALUE; n = 0; average = 0; max = 0; min = Long.MAX_VALUE; } private Stats(Stats original) { mN = original.mN; mAverage = original.mAverage; mMax = original.mMax; mMin = original.mMin; private Stats(int n, double average, long max, long min) { this.n = n; this.average = average; this.max = max; this.min = min; } private Stats(int n, double average, long max, long min) { mN = n; mAverage = average; mMax = max; mMin = min; private Stats(Stats original) { this(original.n, original.average, original.max, original.min); } private void register(long sample) { mAverage = (mAverage * mN + sample) / (mN + 1); mN++; mMax = Math.max(mMax, sample); mMin = Math.min(mMin, sample); average = (average * n + sample) / (n + 1); n++; max = Math.max(max, sample); min = Math.min(min, sample); } } }
services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.backup.transport; import static com.android.server.backup.testing.TransportData.backupTransport; import static com.android.server.backup.testing.TransportData.d2dTransport; import static com.google.common.truth.Truth.assertThat; import android.content.ComponentName; import android.platform.test.annotations.Presubmit; import com.android.server.backup.transport.TransportStats.Stats; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) @SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class TransportStatsTest { private static final double TOLERANCE = 0.0001; private TransportStats mTransportStats; private ComponentName mTransportComponent1; private ComponentName mTransportComponent2; @Before public void setUp() throws Exception { mTransportStats = new TransportStats(); mTransportComponent1 = backupTransport().getTransportComponent(); mTransportComponent2 = d2dTransport().getTransportComponent(); } @Test public void testRegisterConnectionTime() { mTransportStats.registerConnectionTime(mTransportComponent1, 50L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(50); assertThat(stats.max).isEqualTo(50L); assertThat(stats.min).isEqualTo(50L); assertThat(stats.n).isEqualTo(1); } @Test public void testRegisterConnectionTime_whenHasAlreadyOneSample() { mTransportStats.registerConnectionTime(mTransportComponent1, 50L); mTransportStats.registerConnectionTime(mTransportComponent1, 100L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(75); assertThat(stats.max).isEqualTo(100L); assertThat(stats.min).isEqualTo(50L); assertThat(stats.n).isEqualTo(2); } @Test public void testGetStatsForTransport() { mTransportStats.registerConnectionTime(mTransportComponent1, 10L); mTransportStats.registerConnectionTime(mTransportComponent2, 20L); Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1); assertThat(stats.average).isWithin(TOLERANCE).of(10); assertThat(stats.max).isEqualTo(10L); assertThat(stats.min).isEqualTo(10L); assertThat(stats.n).isEqualTo(1); } @Test public void testMerge() { mTransportStats.registerConnectionTime(mTransportComponent1, 10L); mTransportStats.registerConnectionTime(mTransportComponent2, 20L); Stats stats1 = mTransportStats.getStatsForTransport(mTransportComponent1); Stats stats2 = mTransportStats.getStatsForTransport(mTransportComponent2); Stats stats = Stats.merge(stats1, stats2); assertThat(stats.average).isWithin(TOLERANCE).of(15); assertThat(stats.max).isEqualTo(20L); assertThat(stats.min).isEqualTo(10L); assertThat(stats.n).isEqualTo(2); } }