droidcon moscow 2015. android ndk - стоит ли игра свеч Дмитрий Юницкий...
TRANSCRIPT
![Page 1: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/1.jpg)
Android NDK - стоит ли игра свеч?
Юницкий Дмитрий
![Page 2: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/2.jpg)
Agenda• Зачем использовать NDK?•Механизм работы.• Экспериментальный gradle плагин.• Производительность.• Где искать проблемы и как с ними бороться?• Креши в нативном коде.• Размер apk и ABI splits.
2
![Page 3: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/3.jpg)
Зачем?• Критичные по производительности участки кода -
игры, распознавание образов, работа с видео-голосом
• Использование написанного ранее кода или существующих библиотек (OpenCV, ffmpeg, …)
• Написание общего кода для нескольких платформ одновременно
3
![Page 4: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/4.jpg)
Механизм работы.• JNI - набор инструментов для запуска
скомпилированного кода на C/C++/Ассемблере из виртуальной машины Java
• NDK - набор скриптов/тулчейнов/инструментов для использования JNI в Android
• apk содержит скомпилированную под определённый набор ABI нативную библиотеку
• Приложение может быть целиком реализовано на C++ с использованием NativeActivity 4
![Page 5: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/5.jpg)
Вкратце про API.
• Call*Method, Get*Field, Set*Field, New*Array, IsSameObject…
• NewGlobalRef, DeleteGlobalRef, DeleteLocalRef
• AttachCurrentThread, DetachCurrentThread
• JNI_OnLoad, JNI_OnUnload5
JNIEnv:
![Page 6: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/6.jpg)
Экспериментальный плагин gradle.Возможности:• Интеграция NDK• Отладка нативного кода• РефакторингПока не поддерживается:• Интеграция с внешними системами сборки• Сборка статических библиотек• Чистые NDK модули 6
![Page 7: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/7.jpg)
Gradle. Настройка.
7
distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle-experimental:0.2.1' }}
allprojects { repositories { jcenter() }}
gradle-wrapper.properties:
:
build.gradle:
![Page 8: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/8.jpg)
Gradle. Настройка.apply plugin: 'com.android.model.application'
model { android { compileSdkVersion = 22 buildToolsVersion = "22.0.1"
defaultConfig.with { applicationId = "my.test.integration" minSdkVersion.apiLevel = 7 targetSdkVersion.apiLevel = 7 } }
android.ndk { moduleName = "ndk_integration"
cppFlags += "-std=c++11" cppFlags += "-I${file("../external_cpp_sources")}".toString()
ldLibs += ["android", "log"] stl = "stlport_static" }
android.sources { main { jni { source { srcDirs 'src/main/jni', '../external_cpp_sources' } } } }} 8
build.gradle:
![Page 9: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/9.jpg)
Gradle. Настройка.extern "C"{
JNIEXPORT jboolean JNICALLJava_my_test_integration_IntegrationActivity_nativeGetBooleanValue(JNIEnv *env, jobject instance) { SomeCppClass object; return (jboolean) object.getSomeValue();}
} // extern "C"
9
![Page 10: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/10.jpg)
Gradle. Настройка.public class IntegrationActivity extends AppCompatActivity{ … @Override protected void onCreate(Bundle savedInstanceState) { … textView.setText("Value from native code: " + nativeGetBooleanValue()); } public native boolean nativeGetBooleanValue(); static { System.loadLibrary("ndk_integration"); }} 10
![Page 11: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/11.jpg)
Отладка.
11
![Page 12: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/12.jpg)
Производительность.• Оверхед JNI• Бенчмарки?• SSE, NEON• Многообразие компиляторов -
gcc, clang, Intel, Qualcomm…12
![Page 13: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/13.jpg)
Вызов native метода из Java.• Создать новый стекфрейм
• Передать аргументы согласно ABI
• Передать JNIEnv* и jclass(jobject)
• Synchronized
• Проверить исключения
• … 13
![Page 14: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/14.jpg)
Бенчмарки.
14
Запуск native метода
FindClass CallMethod GetMethodId0 мкс
15 мкс
30 мкс
45 мкс
60 мкс
32
3 1 3
44
62 4
55
82 5
![Page 15: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/15.jpg)
Как избегать проблем.• Локальные/глобальные ссылки
• Работа с jni из нативных потоков
• Garbage collector
• Закешируй это! 15
![Page 16: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/16.jpg)
Локальные/глобальные ссылки.• Локальные ссылки - действительны в пределах метода в рамках
одного потока
• Java автоматически очищает локальные ссылки при возврате из нативного метода
• Лимит локальных ссылок
• Объекты, на которые есть ссылки - не могут быть очищены GC
• Глобальные ссылки действительны вплоть до явного освобождения
16
![Page 17: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/17.jpg)
Нативные потоки в JNI.• AttachCurrentThread для работы с jni
• DetachCurrentThread перед завершением
• Локальные ссылки НЕ очищаются автоматически. Необходимо очищать создаваемые ссылки с помощью DeleteLocalRef либо использовать PushLocalFrame/PopLocalFrame
• FindClass НЕ работает. Простой вариант решения - кешировать класс в JNI_OnLoad. Более сложный, но гибкий - кешировать сам ClassLoader. 17
![Page 18: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/18.jpg)
Кеширование JNI объектов. • jClass, возвращаемые FindClass,
GetObjectClass -локальные ссылки, для кеширования необходимо преобразовывать в глобальные.
• jMethodId, jFieldId - просто структуры, можно сохранять без преобразования в глобальные и использовать из любых потоков.
18
![Page 19: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/19.jpg)
Креши в нативном коде.• Coffecatch• Breakpad - кроссплатформенная
библиотека от google• Готовые решения - crashlytics,
hockeyapp и прочие, в основном используют breakpad в своей основе
19
![Page 20: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/20.jpg)
• armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64
• ABI split позволяет собрать различную apk для каждой архитектуры
• Для распространения через Google play требуется различный versionCodeдля каждой версии
20
ABI & multi-apk
![Page 21: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/21.jpg)
…splits { abi { enable true reset() // ABI to build include ‘x86' universalApk true }}……import com.android.build.OutputFileproject.ext.versionCodes = ['x86':1]
android.applicationVariants.all { variant -> variant.outputs.each { output -> if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) { def file = output.outputFile // set different versionCodes for different ABIs int abiVersionCode = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) ?: 0 output.versionCodeOverride = (abiVersionCode * 1000) + android.defaultConfig.versionCode } }}… 21
ABI splitbuild.gradle:
![Page 23: Droidcon Moscow 2015. Android NDK - стоит ли игра свеч Дмитрий Юницкий - Mail.Ru Group](https://reader036.vdocuments.net/reader036/viewer/2022062821/5888a4461a28ab264b8b66c1/html5/thumbnails/23.jpg)
• http://developer.android.com/training/articles/perf-jni.html
• https://developer.android.com/ndk/guides/concepts.html
• http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android
• http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html
• http://tools.android.com/tech-docs/new-build-system/gradle-experimental
• http://normanmaurer.me/blog/2014/01/07/JNI-Performance-Welcome-to-the-dark-side/
• http://compmus.ime.usp.br/sbcm/2013/pt/docs/pos_tec_4.pdf
• http://janet-project.sourceforge.net/papers/jnibench.pdf23
Полезные ссылки.