-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
158 changes: 158 additions & 0 deletions
158
android/core/core/src/androidTest/java/org/coepi/core/JniBenchmarks.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package org.coepi.core | ||
|
||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import org.coepi.core.jni.BenchmarksIntClass | ||
import org.coepi.core.jni.JniApi | ||
import org.junit.Ignore | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* See [testing documentation](http://d.android.com/tools/testing). | ||
*/ | ||
|
||
// NOTE: Ideally this should use benchmark runner | ||
// https://developer.android.com/studio/profile/build-benchmarks-without-gradle | ||
// The documentation is incomplete, though, and it was consuming too much time | ||
// so for now "manual" benchmarks | ||
|
||
@Ignore("Benchmarks") | ||
@ExperimentalCoroutinesApi | ||
@RunWith(AndroidJUnit4::class) | ||
class JniBenchmarks { | ||
|
||
private val jniApi = JniApi() | ||
private val nonJniApi = NonJniApi() | ||
|
||
@Test | ||
fun benchmarkNoopWithJni() { | ||
// 70ms, 97ms, 80ms, 85ms | ||
benchmark("benchmarkNoop") { | ||
for (i in 0..1000000) { | ||
jniApi.noopForBenchmarks() | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkNoopWithoutJni() { | ||
// 22ms, 22ms, 21ms, 22ms | ||
benchmark("benchmarkNoopWithoutJni") { | ||
for (i in 0..1000000) { | ||
nonJniApi.noopForBenchmarks() | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendReceiveIntWithJni() { | ||
// 72ms, 79ms, 89ms, 90ms | ||
benchmark("benchmarkSendReceiveIntWithJni") { | ||
for (i in 0..1000000) { | ||
jniApi.sendReceiveIntForBenchmarks(1) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendReceiveIntWithoutJni() { | ||
// 22ms, 10ms, 23ms, 23ms | ||
benchmark("benchmarkSendReceiveIntWithoutJni") { | ||
for (i in 0..1000000) { | ||
nonJniApi.sendReceiveIntForBenchmarks(1) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendReceiveStringWithJni() { | ||
// 4596ms, 4343ms, 4561ms, 4360ms | ||
benchmark("benchmarkSendReceiveStringWithJni") { | ||
for (i in 0..1000000) { | ||
jniApi.sendCreateStringForBenchmarks("hello") | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendReceiveStringDontUseInputWithJni() { | ||
// 2415ms, 2439ms, 2415ms, 2455ms | ||
benchmark("sendCreateStringDontUseInputForBenchmarks") { | ||
for (i in 0..1000000) { | ||
jniApi.sendCreateStringDontUseInputForBenchmarks("hello") | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendReceiveStringWithoutJni() { | ||
// 12ms, 31ms, 27ms, 27ms | ||
benchmark("benchmarkSendReceiveStringWithoutJni") { | ||
for (i in 0..1000000) { | ||
nonJniApi.sendCreateStringForBenchmarks("hello") | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendClassWithJni() { | ||
// 8639ms, 8690ms, 8476ms, 8694ms | ||
benchmark("benchmarkClassStructWithJni") { | ||
for (i in 0..1000000) { | ||
jniApi.sendClassForBenchmarks(BenchmarksIntClass(1)) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkSendClassWithoutJni() { | ||
// 39ms, 31ms, 32ms, 41ms | ||
benchmark("benchmarkClassStructWithoutJni") { | ||
for (i in 0..1000000) { | ||
nonJniApi.sendClassForBenchmarks(BenchmarksIntClass(1)) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkReturnClassWithJni() { | ||
// 37929ms, 39027ms, 38815ms, 38711ms | ||
benchmark("benchmarkReturnClassWithJni") { | ||
for (i in 0..1000000) { | ||
jniApi.returnClassForBenchmarks() | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun benchmarkReturnClassWithoutJni() { | ||
// 16ms, 40ms, 41ms, 30ms | ||
benchmark("benchmarkReturnClassWithoutJni") { | ||
for (i in 0..1000000) { | ||
nonJniApi.returnClassForBenchmarks() | ||
} | ||
} | ||
} | ||
|
||
private fun benchmark(label: String, f: () -> Unit) { | ||
val tsLong = System.currentTimeMillis() | ||
f() | ||
val ttLong = System.currentTimeMillis() - tsLong | ||
println("$label took: ${ttLong}ms") | ||
} | ||
} | ||
|
||
private class NonJniApi { | ||
fun noopForBenchmarks() {} | ||
|
||
fun sendReceiveIntForBenchmarks(i: Int): Int = 1 | ||
|
||
fun sendCreateStringForBenchmarks(string: String): String = "Return string" | ||
|
||
fun sendClassForBenchmarks(c: BenchmarksIntClass) {} | ||
|
||
fun returnClassForBenchmarks() = BenchmarksIntClass(1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
extern crate jni; | ||
use self::jni::JNIEnv; | ||
use jni::objects::{JClass, JObject, JString, JValue}; | ||
use jni::sys::{jint, jobject, jstring}; | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_noopForBenchmarks(env: JNIEnv, _: JClass) {} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_sendReceiveIntForBenchmarks( | ||
env: JNIEnv, | ||
_: JClass, | ||
i: jint, | ||
) -> jint { | ||
1 | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_sendCreateStringForBenchmarks( | ||
env: JNIEnv, | ||
_: JClass, | ||
string: JString, | ||
) -> jstring { | ||
let string: String = env | ||
.get_string(string) | ||
.expect("Couldn't create java string") | ||
.into(); | ||
|
||
let output = env | ||
.new_string("Return string") | ||
.expect("Couldn't create java string"); | ||
|
||
output.into_inner() | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_sendCreateStringDontUseInputForBenchmarks( | ||
env: JNIEnv, | ||
_: JClass, | ||
string: JString, | ||
) -> jstring { | ||
let output = env | ||
.new_string("Return string") | ||
.expect("Couldn't create java string"); | ||
|
||
output.into_inner() | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_sendClassForBenchmarks( | ||
env: JNIEnv, | ||
_: JClass, | ||
my_struct: JObject, | ||
) { | ||
let my_int_j_value_res = env.get_field(my_struct, "myInt", "I"); | ||
let my_int: i32 = my_int_j_value_res.unwrap().i().unwrap(); | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn Java_org_coepi_core_jni_JniApi_returnClassForBenchmarks( | ||
env: JNIEnv, | ||
_: JClass, | ||
) -> jobject { | ||
let cls = env.find_class("org/coepi/core/jni/BenchmarksIntClass"); | ||
let my_int_j_value = JValue::from(123); | ||
let obj = env.new_object(cls.unwrap(), "(I)V", &[my_int_j_value]); | ||
obj.unwrap().into_inner() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod android_interface; | ||
pub mod ffi_benchmarks; | ||
pub mod ffi_for_sanity_tests; | ||
pub mod jni_domain_tests; |