diff options
-rw-r--r-- | apct-tests/perftests/core/src/android/os/TracePerfTest.java | 86 | ||||
-rw-r--r-- | apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java | 8 | ||||
-rw-r--r-- | api/current.txt | 4 | ||||
-rw-r--r-- | core/java/android/os/Trace.java | 51 | ||||
-rw-r--r-- | core/jni/android_os_Trace.cpp | 89 |
5 files changed, 187 insertions, 51 deletions
diff --git a/apct-tests/perftests/core/src/android/os/TracePerfTest.java b/apct-tests/perftests/core/src/android/os/TracePerfTest.java new file mode 100644 index 000000000000..8e5cfaafde52 --- /dev/null +++ b/apct-tests/perftests/core/src/android/os/TracePerfTest.java @@ -0,0 +1,86 @@ +/* + * 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 android.os; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.perftests.utils.ShellHelper; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class TracePerfTest { + @Rule + public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @BeforeClass + public static void startTracing() { + ShellHelper.runShellCommandRaw("atrace -c --async_start -a *"); + } + + @AfterClass + public static void endTracing() { + ShellHelper.runShellCommandRaw("atrace --async_stop"); + } + + @Before + public void verifyTracingEnabled() { + Assert.assertTrue(Trace.isEnabled()); + } + + @Test + public void testEnabled() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Trace.isEnabled(); + } + } + + @Test + public void testBeginEndSection() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Trace.beginSection("testBeginEndSection"); + Trace.endSection(); + } + } + + @Test + public void testAsyncBeginEnd() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Trace.beginAsyncSection("testAsyncBeginEnd", 42); + Trace.endAsyncSection("testAsyncBeginEnd", 42); + } + } + + @Test + public void testCounter() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Trace.setCounter("testCounter", 123); + } + } +} diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java index cae87fb9c6e4..895547df0393 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java @@ -37,6 +37,14 @@ public final class ShellHelper { @NonNull public static String runShellCommand(@NonNull String template, Object...args) { String command = String.format(template, args); + return runShellCommandRaw(command); + } + + /** + * Runs a Shell command, returning a trimmed response. + */ + @NonNull + public static String runShellCommandRaw(@NonNull String command) { UiAutomation automan = InstrumentationRegistry.getInstrumentation() .getUiAutomation(); ParcelFileDescriptor pfd = automan.executeShellCommand(command); diff --git a/api/current.txt b/api/current.txt index aff03095844e..9c9d8c55c6b0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -33278,8 +33278,12 @@ package android.os { } public final class Trace { + method public static void beginAsyncSection(java.lang.String, int); method public static void beginSection(java.lang.String); + method public static void endAsyncSection(java.lang.String, int); method public static void endSection(); + method public static boolean isEnabled(); + method public static void setCounter(java.lang.String, int); } public class TransactionTooLargeException extends android.os.RemoteException { diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index 583f060f2e0c..a967b3da339e 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -288,6 +288,19 @@ public final class Trace { } /** + * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate + * string creation for trace sections that require formatting. It is not necessary + * to guard all Trace method calls as they internally already check this. However it is + * recommended to use this to prevent creating any temporary objects that would then be + * passed to those methods to reduce runtime cost when tracing isn't enabled. + * + * @return true if tracing is currently enabled, false otherwise + */ + public static boolean isEnabled() { + return isTagEnabled(TRACE_TAG_APP); + } + + /** * Writes a trace message to indicate that a given section of code has begun. This call must * be followed by a corresponding call to {@link #endSection()} on the same thread. * @@ -319,4 +332,42 @@ public final class Trace { nativeTraceEnd(TRACE_TAG_APP); } } + + /** + * Writes a trace message to indicate that a given section of code has + * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same + * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()}, + * asynchronous events do not need to be nested. The name and cookie used to + * begin an event must be used to end it. + * + * @param methodName The method name to appear in the trace. + * @param cookie Unique identifier for distinguishing simultaneous events + */ + public static void beginAsyncSection(String methodName, int cookie) { + asyncTraceBegin(TRACE_TAG_APP, methodName, cookie); + } + + /** + * Writes a trace message to indicate that the current method has ended. + * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)} + * using the same name and cookie. + * + * @param methodName The method name to appear in the trace. + * @param cookie Unique identifier for distinguishing simultaneous events + */ + public static void endAsyncSection(String methodName, int cookie) { + asyncTraceEnd(TRACE_TAG_APP, methodName, cookie); + } + + /** + * Writes trace message to indicate the value of a given counter. + * + * @param counterName The counter name to appear in the trace. + * @param counterValue The counter value. + */ + public static void setCounter(String counterName, int counterValue) { + if (isTagEnabled(TRACE_TAG_APP)) { + nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue); + } + } } diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp index 4f4e5da22c8d..f7dab428abe7 100644 --- a/core/jni/android_os_Trace.cpp +++ b/core/jni/android_os_Trace.cpp @@ -14,93 +14,80 @@ * limitations under the License. */ -#define LOG_TAG "Trace" -// #define LOG_NDEBUG 0 - -#include <inttypes.h> +#include <jni.h> #include <cutils/trace.h> -#include <utils/String8.h> #include <log/log.h> - #include <nativehelper/JNIHelp.h> -#include <nativehelper/ScopedUtfChars.h> -#include <nativehelper/ScopedStringChars.h> + +#include <array> namespace android { -static void sanitizeString(String8& utf8Chars) { - size_t size = utf8Chars.size(); - char* str = utf8Chars.lockBuffer(size); +inline static void sanitizeString(char* str, size_t size) { for (size_t i = 0; i < size; i++) { char c = str[i]; if (c == '\0' || c == '\n' || c == '|') { str[i] = ' '; } } - utf8Chars.unlockBuffer(); } -static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) { +inline static void getString(JNIEnv* env, jstring jstring, char* outBuffer, jsize maxSize) { + jsize size = std::min(env->GetStringLength(jstring), maxSize); + env->GetStringUTFRegion(jstring, 0, size, outBuffer); + sanitizeString(outBuffer, size); + outBuffer[size] = '\0'; +} + +template<typename F> +inline static void withString(JNIEnv* env, jstring jstr, F callback) { + std::array<char, 1024> buffer; + getString(env, jstr, buffer.data(), buffer.size()); + callback(buffer.data()); +} + +static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) { return atrace_get_enabled_tags(); } -static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz, +static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint value) { - ScopedUtfChars name(env, nameStr); - - ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, name.c_str(), value); - atrace_int(tag, name.c_str(), value); + withString(env, nameStr, [tag, value](char* str) { + atrace_int(tag, str, value); + }); } -static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz, +static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr) { - ScopedStringChars jchars(env, nameStr); - String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); - sanitizeString(utf8Chars); - - ALOGV("%s: %" PRId64 " %s", __FUNCTION__, tag, utf8Chars.string()); - atrace_begin(tag, utf8Chars.string()); + withString(env, nameStr, [tag](char* str) { + atrace_begin(tag, str); + }); } -static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz, - jlong tag) { - - ALOGV("%s: %" PRId64, __FUNCTION__, tag); +static void android_os_Trace_nativeTraceEnd(JNIEnv*, jclass, jlong tag) { atrace_end(tag); } -static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass clazz, +static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { - ScopedStringChars jchars(env, nameStr); - String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); - sanitizeString(utf8Chars); - - ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); - atrace_async_begin(tag, utf8Chars.string(), cookie); + withString(env, nameStr, [tag, cookie](char* str) { + atrace_async_begin(tag, str, cookie); + }); } -static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass clazz, +static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass, jlong tag, jstring nameStr, jint cookie) { - ScopedStringChars jchars(env, nameStr); - String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size()); - sanitizeString(utf8Chars); - - ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie); - atrace_async_end(tag, utf8Chars.string(), cookie); + withString(env, nameStr, [tag, cookie](char* str) { + atrace_async_end(tag, str, cookie); + }); } -static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv* env, - jclass clazz, jboolean allowed) { - ALOGV("%s: %d", __FUNCTION__, allowed); - +static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) { atrace_set_debuggable(allowed); } -static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env, - jclass clazz, jboolean enabled) { - ALOGV("%s: %d", __FUNCTION__, enabled); - +static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean enabled) { atrace_set_tracing_enabled(enabled); } |