Прискорюємо додаток Android за допомогою Golang

image

Розробка мобільних додатків — це завжди компроміс між тим, що хочеться зробити, і тим, що дозволяє зробити платформа пристрою. У цій статті розповідається про те, як збільшити можливості програми Android за допомогою Golang.

Тут ви не знайдете витоку секретного api android. Використовувані механізми — це стандартні (або майже стандартні інструменти android і golang, опис яких є на офіційних сайтах і профільних форумах. Але у вигляді єдиного плану дій, та ще й російською мовою — таке публікується вперше і ексклюзивно для Хабра.

Передісторія
По численних проханнях користувачів в одному з додатків були розроблені передбачення тексту. Передбачення обслуговував алгоритм radix tree, реалізований в окремій android-бібліотеці. Алгоритм показував хорошу продуктивність поряд з економним споживанням ресурсів — видавав результат за десятки мілісекунд при споживанні 1,5 Мб пам'яті. Цілком робочі показники. Але так було тільки при ізольованому тестуванні бібліотеки на JVM.

Проблеми почалися при підключенні до бібліотеки з додатком. На android алгоритм пророкувань став гальмувати, видача результатів затягнулася до 7 секунд. Нічого собі! Так за 7 секунд можна вручну набрати слово, стерти і набрати його правильно. Такі передбачення нікуди не годилися.

Проведений аналіз не виявив проблем коду. Алгоритм працював бездоганно, пам'яті споживав у строго відведених кількостях, не відволікався на сторонні процеси, всі асинхронно, апаратних ресурсів предостатньо. Висновок напрошувався тільки один — віртуальна машина android dalvik має продуктивність, відмінну від JVM, і в рамках dalvik даний код приречений на гальма.

Тоді і було вирішено, що алгоритм пророкувань потрібно виносити з dalvik. Для цього існує JNI — Java Native Interface. Механізм, що дозволяє викликати з java методи бібліотек, написаних на C/C++. І назад, — з бібліотеки C/C++ викликати методи java.

Рішення
Для створення нативної бібліотеки був обраний мову Go. Просто тому що є досвід роботи з ним, на відміну від C/C++. Golang чудовий, але цей шлях має свої труднощі, оскільки ми отримуємо додатковий рівень складності. Для чистого C/C++ достатньо використовувати NDK та слідувати інструкціям, наведеним на сайті android developers. Для Golang доведеться вивчити ще й компіляцію golang під android, почати можна тут.

Попереду лежав шлях, повний небезпек і пригод. Але зараз цей шлях вже пройдений, і я із задоволенням поділюся його планом.

План
Середовище розробки android:
  • ОС: Windows 7.
  • IDE: Eclipse with ADT. Але цей план підійде і для Android Studio.
Середовище розробки golang:
  • ОС: Для компіляції golang під android використовується linux. Я використовую Ubuntu 14.04, запущену на VirtualBox.
  • Android SDK.
    — Завантажити архів з офіційного сайту android
    — Розпакувати, припустимо,
    $HOME/android/android-sdk-linux
  • Java JDK.
    $ apt-get default-jdk
  • Go 1.5.
    Поточна версія релізу Go — 1.4. Але у мене не вийшло скомпілювати бібліотеку з його допомогою, десь помилився при складанні toolchain. Тому використовував пакет gomobile з девелоперської версією Go 1.5, реліз якої ще тільки планується. Поки що немає релізу, установка Go 1.5 описана тут:
    — Встановити Go 1.4 golang.org/doc/install
    — Клонувати поточний репозиторій golang:
    $ git clone https://go.googlesource.com/go $HOME/go
    — Скомпілювати поточну версію Go з допомогою Go 1.4
    $ export GOROOT_BOOTSTRAP=/usr/local/go
    $ cd $HOME/go/src && ./make.bash
    $ export PATH=$PATH:$HOME/go/bin
  • Встановити і ініціалізувати пакет gomobile.
    $ go get golang.org/x/mobile/cmd/gomobile
    $ gomobile init
    Ініціалізація пакету займає пристойний час
Розробка бібліотеки golang.
  • Розробляється звичайний golang package, ніяких додаткових рекомендацій. Експортні методи будуть доступні з android.
Компіляція бібліотеки golang в бібліотеку android *.aar.
  • Використовувати команду gomobile bind з зазначенням шляху до android sdk
    $ cd <golang project folder>
    $ ANDROID_HOME=$HOME/android/android-sdk-linux gomobile bind
Підключення бібліотеки *.aar до додатка:
Перш за все, передати бібліотеку *.aar на машину розробки android. Далі в залежності від IDE.

для Eclipse:
  • Розпакувати бібліотеку *.aar в тимчасовий каталог
  • Eclipse створити новий проект з існуючого коду, вказавши тимчасовий каталог з п. 1
  • Зазначити, що даний проект є бібліотекою android
  • Підключити каталог jni і файл classes.jar у Build Path нового проекту
  • Підключити новий проект як бібліотеку в проект програми
  • Скопіювати вміст папки jni в папку libs проекту програми.
  • Скопіювати вміст proguard.txt бібліотеки proguard.txt проекту програми (захист класів go* від обфускации)
  • При наступних оновленнях бібліотеки *.aar достатньо оновити файли в папках jni, libs і файл classes.jar
для Android Studio:
  • Підключити готову бібліотеку *.aar до проекту, використовуючи стандартні засоби Android Studio. На жаль, у мене немає такого досвіду, тому залишаю це в якості домашнього завдання.
Виклик методів нативної бібліотеки з android.
  • Перед використанням нативної бібліотеки у програмі, потрібно виконати ініціалізацію. Підходяще для цього місце — в методі onCreate:

    public class MyActivity extends Activity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R. layout.activity_my);
    
    Go.init(getContext());
    }
    } 
    
  • Методи бібліотеки golang доступні через package, однойменні з тими, що ви визначили в golang. Наприклад:
    golang:

    package radix
    ...
    func Suggest(params string) string {
    ...
    }
    

    java:
    suggestions = Radix.Suggest(params);
    
Результат
Після перенесення алгоритму в нативну бібліотеку, передбачення стали працювати навіть швидше, ніж в JVM — результат віддається менш ніж за 10 мс. Також зменшилася кількість garbage collection, тому що частина ресурсів була передана на бік нативного коду.

Ефект від впровадження JNI перевершив очікування. З такими показниками клавіатура і відправилася в реліз.

Висновок
Прискорити додаток android за допомогою golang — це зовсім не теорія, а реальна можливість, яка вже використовується в додатках маркету.

Звичайно, це ускладнює розробку додатків, зоопарк інструментів подвоюється. Але це дає можливість реалізувати цікаві рішення.

З виходом Go 1.5 очікується, що інтеграція android-golang стане ще доступнішим, за рахунок інструментарію gomobile, який скорочує весь процес до 2-х команд.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.