1 #include <jni.h>
2 
3 #include <pthread.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <string>
7 
8 #define noinline __attribute__((__noinline__))
9 
10 extern "C"
11 JNIEXPORT jstring JNICALL
Java_com_example_simpleperf_simpleperfexamplewithnative_MainActivity_stringFromJNI(JNIEnv * env,jobject)12 Java_com_example_simpleperf_simpleperfexamplewithnative_MainActivity_stringFromJNI(
13         JNIEnv *env,
14         jobject /* this */) {
15     std::string hello = "Hello from C++";
16     return env->NewStringUTF(hello.c_str());
17 }
18 
ThrowErrnoException(JNIEnv * env,const char * function_name,int err)19 static void ThrowErrnoException(JNIEnv* env, const char* function_name, int err) {
20     jclass cls = env->FindClass("android/system/ErrnoException");
21     if (cls == nullptr) {
22         return;
23     }
24     jmethodID cid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;I)V");
25     if (cid == nullptr) {
26         return;
27     }
28     jstring msg = env->NewStringUTF(function_name);
29     if (msg == nullptr) {
30         return;
31     }
32     jthrowable obj = (jthrowable)env->NewObject(cls, cid, msg, err);
33     if (obj == nullptr) {
34         return;
35     }
36     env->Throw(obj);
37 }
38 
CallFunction(int a)39 int CallFunction(int a) {
40     return a + atoi("1");
41 }
42 
BusyLoopThread(void *)43 static void* BusyLoopThread(void*) {
44     volatile int i = 0;
45     while (true) {
46         i = CallFunction(i);
47     }
48     return nullptr;
49 }
50 
51 extern "C"
52 JNIEXPORT void JNICALL
Java_com_example_simpleperf_simpleperfexamplewithnative_MainActivity_createBusyThreadFromJNI(JNIEnv * env,jobject)53 Java_com_example_simpleperf_simpleperfexamplewithnative_MainActivity_createBusyThreadFromJNI(
54         JNIEnv *env,
55         jobject /* this */) {
56     pthread_t thread;
57     int ret = pthread_create(&thread, nullptr, BusyLoopThread, nullptr);
58     if (ret) {
59         ThrowErrnoException(env, "pthread_create", ret);
60         return;
61     }
62 }
63 
GetSystemClock()64 static inline uint64_t GetSystemClock() {
65     timespec ts;
66     clock_gettime(CLOCK_MONOTONIC, &ts);
67     return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
68 }
69 
70 constexpr int LOOP_COUNT = 100000000;
RunFunction()71 static uint64_t noinline RunFunction() {
72     uint64_t start_time_in_ns = GetSystemClock();
73     for (volatile int i = 0; i < LOOP_COUNT; ++i) {
74     }
75     return GetSystemClock() - start_time_in_ns;
76 }
77 
SleepFunction(unsigned long long sleep_time_in_ns)78 static uint64_t noinline SleepFunction(unsigned long long sleep_time_in_ns) {
79     uint64_t start_time_in_ns = GetSystemClock();
80     struct timespec req;
81     req.tv_sec = sleep_time_in_ns / 1000000000;
82     req.tv_nsec = sleep_time_in_ns % 1000000000;
83     nanosleep(&req, nullptr);
84     return GetSystemClock() - start_time_in_ns;
85 }
86 
SleepThread(void *)87 static void* SleepThread(void*) {
88     pthread_setname_np(pthread_self(), "SleepThread");
89     uint64_t total_sleep_time_in_ns = 0;
90     uint64_t total_run_time_in_ns = 0;
91     while (true) {
92         total_run_time_in_ns += RunFunction();
93         if (total_sleep_time_in_ns < total_run_time_in_ns) {
94             total_sleep_time_in_ns += SleepFunction(total_run_time_in_ns - total_sleep_time_in_ns);
95         }
96     }
97 }
98 
99 extern "C"
100 JNIEXPORT void JNICALL
Java_com_example_simpleperf_simpleperfexamplewithnative_SleepActivity_createSleepThreadFromJNI(JNIEnv * env,jobject)101 Java_com_example_simpleperf_simpleperfexamplewithnative_SleepActivity_createSleepThreadFromJNI(
102         JNIEnv *env,
103         jobject /* this */) {
104     pthread_t thread;
105     int ret = pthread_create(&thread, nullptr, SleepThread, nullptr);
106     if (ret) {
107         ThrowErrnoException(env, "pthread_create", ret);
108         return;
109     }
110 }
111 
112 extern "C"
113 JNIEXPORT int JNICALL
Java_com_example_simpleperf_simpleperfexamplewithnative_MixActivity_callFunction(JNIEnv * env,jobject,int a)114 Java_com_example_simpleperf_simpleperfexamplewithnative_MixActivity_callFunction(
115         JNIEnv *env,
116         jobject /* this */,
117         int a) {
118     return CallFunction(a);
119 }