diff options
-rw-r--r-- | core/java/android/os/Looper.java | 14 | ||||
-rw-r--r-- | core/java/android/os/SystemClock.java | 18 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 50 | ||||
-rw-r--r-- | core/jni/android_os_SystemClock.cpp | 36 |
4 files changed, 104 insertions, 14 deletions
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index 720e802b..c61f28a 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -130,19 +130,20 @@ public class Looper { if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); - wallStart = System.currentTimeMillis(); - threadStart = SystemClock.currentThreadTimeMillis(); + wallStart = SystemClock.currentTimeMicro(); + threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg); if (logging != null) { - long wallTime = System.currentTimeMillis() - wallStart; - long threadTime = SystemClock.currentThreadTimeMillis() - threadStart; + long wallTime = SystemClock.currentTimeMicro() - wallStart; + long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { - ((Profiler) logging).profile(msg, wallStart, wallTime, threadTime); + ((Profiler) logging).profile(msg, wallStart, wallTime, + threadStart, threadTime); } } @@ -247,6 +248,7 @@ public class Looper { * @hide */ public static interface Profiler { - void profile(Message message, long wallStart, long wallTime, long threadTime); + void profile(Message message, long wallStart, long wallTime, + long threadStart, long threadTime); } } diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 2dd6749..7291739 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -157,4 +157,22 @@ public final class SystemClock { * @return elapsed milliseconds in the thread */ public static native long currentThreadTimeMillis(); + + /** + * Returns microseconds running in the current thread. + * + * @return elapsed microseconds in the thread + * + * @hide + */ + public static native long currentThreadTimeMicro(); + + /** + * Returns current wall time in microseconds. + * + * @return elapsed microseconds in wall time + * + * @hide + */ + public static native long currentTimeMicro(); } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index b85159b..3798c9d 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -26,6 +26,7 @@ import android.os.Environment; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; import android.util.Printer; @@ -53,6 +54,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -455,11 +457,19 @@ public class ViewDebug { private static final String LOG_TAG = "LooperProfiler"; + private final long mTraceWallStart; + private final long mTraceThreadStart; + private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512); private final File mTraceFile; - public LooperProfiler(File traceFile) { + private final HashMap<String, Short> mTraceNames = new HashMap<String, Short>(32); + private short mTraceId = 0; + + LooperProfiler(File traceFile) { mTraceFile = traceFile; + mTraceWallStart = SystemClock.currentTimeMicro(); + mTraceThreadStart = SystemClock.currentThreadTimeMicro(); } @Override @@ -468,17 +478,28 @@ public class ViewDebug { } @Override - public void profile(Message message, long wallStart, long wallTime, long threadTime) { + public void profile(Message message, long wallStart, long wallTime, + long threadStart, long threadTime) { Entry entry = new Entry(); - entry.messageId = message.what; - entry.name = message.getTarget().getMessageName(message); + entry.traceId = getTraceId(message); entry.wallStart = wallStart; entry.wallTime = wallTime; + entry.threadStart = threadStart; entry.threadTime = threadTime; mTraces.add(entry); } + private short getTraceId(Message message) { + String name = message.getTarget().getMessageName(message); + Short traceId = mTraceNames.get(name); + if (traceId == null) { + traceId = mTraceId++; + mTraceNames.put(name, traceId); + } + return traceId; + } + void save() { // Don't block the UI thread new Thread(new Runnable() { @@ -502,6 +523,14 @@ public class ViewDebug { try { out.writeInt(LOOPER_PROFILER_VERSION); + out.writeLong(mTraceWallStart); + out.writeLong(mTraceThreadStart); + + out.writeInt(mTraceNames.size()); + for (Map.Entry<String, Short> entry : mTraceNames.entrySet()) { + saveTraceName(entry.getKey(), entry.getValue(), out); + } + out.writeInt(mTraces.size()); for (Entry entry : mTraces) { saveTrace(entry, out); @@ -519,19 +548,24 @@ public class ViewDebug { } } + private void saveTraceName(String name, short id, DataOutputStream out) throws IOException { + out.writeShort(id); + out.writeUTF(name); + } + private void saveTrace(Entry entry, DataOutputStream out) throws IOException { - out.writeInt(entry.messageId); - out.writeUTF(entry.name); + out.writeShort(entry.traceId); out.writeLong(entry.wallStart); out.writeLong(entry.wallTime); + out.writeLong(entry.threadStart); out.writeLong(entry.threadTime); } static class Entry { - int messageId; - String name; + short traceId; long wallStart; long wallTime; + long threadStart; long threadTime; } } diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp index ffd0c1e..66d58cd 100644 --- a/core/jni/android_os_SystemClock.cpp +++ b/core/jni/android_os_SystemClock.cpp @@ -80,6 +80,38 @@ static jlong android_os_SystemClock_currentThreadTimeMillis(JNIEnv* env, } /* + * native public static long currentThreadTimeMicro(); + */ +static jlong android_os_SystemClock_currentThreadTimeMicro(JNIEnv* env, + jobject clazz) +{ +#if defined(HAVE_POSIX_CLOCKS) + struct timespec tm; + + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); + + return tm.tv_sec * 1000000LL + tm.tv_nsec / 1000; +#else + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_nsec / 1000; +#endif +} + +/* + * native public static long currentTimeMicro(); + */ +static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env, + jobject clazz) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_usec; +} + +/* * JNI registration. */ static JNINativeMethod gMethods[] = { @@ -92,6 +124,10 @@ static JNINativeMethod gMethods[] = { (void*) android_os_SystemClock_elapsedRealtime }, { "currentThreadTimeMillis", "()J", (void*) android_os_SystemClock_currentThreadTimeMillis }, + { "currentThreadTimeMicro", "()J", + (void*) android_os_SystemClock_currentThreadTimeMicro }, + { "currentTimeMicro", "()J", + (void*) android_os_SystemClock_currentTimeMicro }, }; int register_android_os_SystemClock(JNIEnv* env) { |