diff options
author | 2018-03-22 17:42:13 +0000 | |
---|---|---|
committer | 2018-03-22 17:42:13 +0000 | |
commit | c7f6eadffc0a243618ce09ee8d6bb8235738135d (patch) | |
tree | 1534e6d9ca90b60168515c51063f97d9cceb2b98 | |
parent | 9e64c01d02d8054a78efc60b333ccf86499a337f (diff) | |
parent | d0b64e6902b92f261584c6297840f9a2f99bfc8d (diff) |
Merge "Move provider access stats to frameworks/base" into pi-dev
-rw-r--r-- | core/java/com/android/internal/util/ProviderAccessStats.java | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/core/java/com/android/internal/util/ProviderAccessStats.java b/core/java/com/android/internal/util/ProviderAccessStats.java new file mode 100644 index 000000000000..c3ffb02c22f1 --- /dev/null +++ b/core/java/com/android/internal/util/ProviderAccessStats.java @@ -0,0 +1,134 @@ +/* + * 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.internal.util; + +import android.os.SystemClock; +import android.util.SparseBooleanArray; +import android.util.SparseLongArray; + +import java.io.PrintWriter; + +public class ProviderAccessStats { + private final Object mLock = new Object(); + + private final long mStartUptime = SystemClock.uptimeMillis(); + + private final SparseBooleanArray mAllCallingUids = new SparseBooleanArray(); + private final SparseLongArray mQueryStats = new SparseLongArray(16); + private final SparseLongArray mBatchStats = new SparseLongArray(0); + private final SparseLongArray mInsertStats = new SparseLongArray(0); + private final SparseLongArray mUpdateStats = new SparseLongArray(0); + private final SparseLongArray mDeleteStats = new SparseLongArray(0); + private final SparseLongArray mInsertInBatchStats = new SparseLongArray(0); + private final SparseLongArray mUpdateInBatchStats = new SparseLongArray(0); + private final SparseLongArray mDeleteInBatchStats = new SparseLongArray(0); + + private final SparseLongArray mOperationDurationMillis = new SparseLongArray(16); + + private static class PerThreadData { + public int nestCount; + public long startUptimeMillis; + } + + private final ThreadLocal<PerThreadData> mThreadLocal = + ThreadLocal.withInitial(() -> new PerThreadData()); + + private void incrementStats(int callingUid, SparseLongArray stats) { + synchronized (mLock) { + stats.put(callingUid, stats.get(callingUid) + 1); + mAllCallingUids.put(callingUid, true); + } + + final PerThreadData data = mThreadLocal.get(); + data.nestCount++; + if (data.nestCount == 1) { + data.startUptimeMillis = SystemClock.uptimeMillis(); + } + } + + private void incrementStats(int callingUid, boolean inBatch, + SparseLongArray statsNonBatch, SparseLongArray statsInBatch) { + incrementStats(callingUid, inBatch ? statsInBatch : statsNonBatch); + } + + public final void incrementInsertStats(int callingUid, boolean inBatch) { + incrementStats(callingUid, inBatch, mInsertStats, mInsertInBatchStats); + } + + public final void incrementUpdateStats(int callingUid, boolean inBatch) { + incrementStats(callingUid, inBatch, mUpdateStats, mUpdateInBatchStats); + } + + public final void incrementDeleteStats(int callingUid, boolean inBatch) { + incrementStats(callingUid, inBatch, mDeleteStats, mDeleteInBatchStats); + } + + public final void incrementQueryStats(int callingUid) { + incrementStats(callingUid, mQueryStats); + } + + public final void incrementBatchStats(int callingUid) { + incrementStats(callingUid, mBatchStats); + } + + public void finishOperation(int callingUid) { + final PerThreadData data = mThreadLocal.get(); + data.nestCount--; + if (data.nestCount == 0) { + // Because we only have millisecond granularity, let's always attribute at least 1ms + // for each operation. + final long duration = Math.max(1, SystemClock.uptimeMillis() - data.startUptimeMillis); + + synchronized (mLock) { + mOperationDurationMillis.put(callingUid, + mOperationDurationMillis.get(callingUid) + duration); + } + } + } + + public void dump(PrintWriter pw, String prefix) { + synchronized (mLock) { + pw.print(" Process uptime: "); + pw.print((SystemClock.uptimeMillis() - mStartUptime) / (60 * 1000)); + pw.println(" minutes"); + pw.println(); + + pw.print(prefix); + pw.println("Client activities:"); + pw.print(prefix); + pw.println(" UID Query Insert Update Delete Batch Insert Update Delete" + + " Sec"); + for (int i = 0; i < mAllCallingUids.size(); i++) { + final int uid = mAllCallingUids.keyAt(i); + pw.print(prefix); + pw.println(String.format( + " %-9d %6d %6d %6d %6d %6d %6d %6d %6d %12.3f", + uid, + mQueryStats.get(uid), + mInsertStats.get(uid), + mUpdateStats.get(uid), + mDeleteStats.get(uid), + mBatchStats.get(uid), + mInsertInBatchStats.get(uid), + mUpdateInBatchStats.get(uid), + mDeleteInBatchStats.get(uid), + (mOperationDurationMillis.get(uid) / 1000.0) + )); + } + pw.println(); + } + } +} |