1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/android/jni_android.h"
6
7 #include "base/at_exit.h"
8 #include "base/logging.h"
9 #include "base/threading/thread.h"
10 #include "base/time/time.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 using ::testing::StartsWith;
15
16 namespace base {
17 namespace android {
18
19 namespace {
20
21 std::atomic<jmethodID> g_atomic_id(nullptr);
LazyMethodIDCall(JNIEnv * env,jclass clazz,int p)22 int LazyMethodIDCall(JNIEnv* env, jclass clazz, int p) {
23 jmethodID id = base::android::MethodID::LazyGet<
24 base::android::MethodID::TYPE_STATIC>(
25 env, clazz,
26 "abs",
27 "(I)I",
28 &g_atomic_id);
29
30 return env->CallStaticIntMethod(clazz, id, p);
31 }
32
MethodIDCall(JNIEnv * env,jclass clazz,jmethodID id,int p)33 int MethodIDCall(JNIEnv* env, jclass clazz, jmethodID id, int p) {
34 return env->CallStaticIntMethod(clazz, id, p);
35 }
36
37 } // namespace
38
TEST(JNIAndroidMicrobenchmark,MethodId)39 TEST(JNIAndroidMicrobenchmark, MethodId) {
40 JNIEnv* env = AttachCurrentThread();
41 ScopedJavaLocalRef<jclass> clazz(GetClass(env, "java/lang/Math"));
42 base::Time start_lazy = base::Time::Now();
43 int o = 0;
44 for (int i = 0; i < 1024; ++i)
45 o += LazyMethodIDCall(env, clazz.obj(), i);
46 base::Time end_lazy = base::Time::Now();
47
48 jmethodID id = g_atomic_id;
49 base::Time start = base::Time::Now();
50 for (int i = 0; i < 1024; ++i)
51 o += MethodIDCall(env, clazz.obj(), id, i);
52 base::Time end = base::Time::Now();
53
54 // On a Galaxy Nexus, results were in the range of:
55 // JNI LazyMethodIDCall (us) 1984
56 // JNI MethodIDCall (us) 1861
57 LOG(ERROR) << "JNI LazyMethodIDCall (us) " <<
58 base::TimeDelta(end_lazy - start_lazy).InMicroseconds();
59 LOG(ERROR) << "JNI MethodIDCall (us) " <<
60 base::TimeDelta(end - start).InMicroseconds();
61 LOG(ERROR) << "JNI " << o;
62 }
63
TEST(JNIAndroidTest,GetJavaStackTraceIfPresent)64 TEST(JNIAndroidTest, GetJavaStackTraceIfPresent) {
65 // The main thread should always have Java frames in it.
66 EXPECT_THAT(GetJavaStackTraceIfPresent(), StartsWith("\tat"));
67
68 class HelperThread : public Thread {
69 public:
70 HelperThread()
71 : Thread("TestThread"), java_stack_1_("X"), java_stack_2_("X") {}
72
73 void Init() override {
74 // Test without a JNIEnv.
75 java_stack_1_ = GetJavaStackTraceIfPresent();
76
77 // Test with a JNIEnv but no Java frames.
78 AttachCurrentThread();
79 java_stack_2_ = GetJavaStackTraceIfPresent();
80 }
81
82 std::string java_stack_1_;
83 std::string java_stack_2_;
84 };
85
86 HelperThread t;
87 t.StartAndWaitForTesting();
88 EXPECT_EQ(t.java_stack_1_, "");
89 EXPECT_EQ(t.java_stack_2_, "");
90 }
91
92 } // namespace android
93 } // namespace base
94