Ottimizzare app Android per architetture Intel x86

24 settembre 2014

Sviluppare app per Android è una delle competenze oggi più richieste nell’ambito dell’IT, e sta raggiungendo una complessità non indifferente. Sono infatti numerosi i dettagli da curare nella produzione di un’applicazione mobile di alta qualità, e ciò è particolarmente vero per Android, caratterizzato dall’essere il sistema operativo di un larghissimo numero di dispositivi (smartphone e tablet per lo più, ma anche dispositivi di diversa forma e natura).

La crescita di Android e la diversificazione degli ambienti in cui è eseguito hanno comportato la necessità di eseguire app su dispositivi con processori Intel x86, architetturalmente differenti e non compatibili con le CPU ARM per le quali questo sistema operativo era originariamente nato. Eseguire un’app su un dispositivo con architettura Intel x86 implica, su Android, la necessità di virtualizzarne l’esecuzione, con un conseguente degrado in termini di performance. Per evitare questo, esistono diversi strumenti che consentono l’ottimizzazione delle app per l’esecuzione sulle architetture x86. In questo articolo vedremo proprio quali espedienti adottare per raggiungere questo scopo.

Android e le architetture x86

Sin dall’uscita di Android, la maggior parte dei dispositivi supportati si basava sull’architettura ARM, ed ancora oggi quest’ultima continua ad essere la soluzione più diffusa tra gli smartphone ed i tablet che adottano questo sistema operativo. Con la crescita di questo sistema operativo e la sua diffusione, però, sono stati prodotti anche un certo numero di device che utilizzano processori Intel, basati su architettura x86. Il numero di questi dispositivi è certamente inferiore a quelli basati su ARM, ma non può essere ritenuto esiguo; al contrario, le architetture x86 potrebbero riscuotere un discreto e crescente successo anche tra i dispositivi mobile. Basti pensare che il Samsung Galaxy Tab 3, che è il tablet Android più venduto al mondo, è dotato di un processore Intel x86.

Perché è importante essere a conoscenza di questa nuova tendenza? Che cosa comporta per uno sviluppatore il fatto che le architetture x86 sono, oggi, una realtà non trascurabile del mondo Android?

Le risposte a queste domande hanno principalmente a che fare con le performance. Se non ci occupiamo esplicitamente di ottimizzare i nostri prodotti per l’esecuzione sulle architetture x86, le conseguenze possono essere due:

  • riduzione delle performance dell’app: la mancata ottimizzazione delle app può comportare un overhead computazionale non indifferente, rallentando l’esecuzione del codice nativo. Ciò può infastidire l’utente, ed indurlo a disinstallare l’app;
  • riduzione delle performance dell’intero dispositivo: anche ammettendo che l’utente si accontenti delle performance dell’app, la mancata ottimizzazione può implicare un aumento dei consumi di memoria e batteria. Esistono (e sono sempre più diffuse) molte app per l’analisi delle prestazioni e dei consumi, che suggeriscono all’utente quali applicazioni utilizzano maggiormente le risorse. Tramite questi tool è molto probabile che la nostra app venga segnalata come “troppo dispendiosa”, e ciò aumenta il rischio che l’utente scelga di disinstallarla.

Per minimizzare le possibilità che l’utente decida di disinstallare la nostra app (cosa che, nella maggior parte dei casi, si traduce in perdite o mancati guadagni), non resta che ottimizzarla. Per nostra fortuna, gli accorgimenti da attuare sono abbastanza semplici, e nel seguito vedremo insieme come fare.

Compilare le app per x86

Prima di spiegare come abilitare la compilazione per le architetture x86 bisogna chiarire il processo di compilazione delle app per Android. Con le impostazioni di default, gli SDK creano un pacchetto .apk della nostra applicazione, che contiene le versioni binarie del codice nativo (quello, cioè, scritto in C o C++, per esempio utilizzando l’NDK di Android) ed il bytecode risultante dalla compilazione del codice Java.

Mentre il bytecode viene necessariamente virtualizzato (ed è quindi indipendente dall’architettura sottostante), il codice nativo viene compilato generalmente per le sole architetture ARM, ed il codice binario è incluso nel pacchetto .apk che rappresenta la nostra app.

È quindi chiaro che, se scriviamo un’app utilizzando soltanto Java, non avremo la necessità di compilare per le diverse architetture, perché il bytecode deve necessariamente essere eseguito in virtualizzazione sulla Dalvik Virtual Machine. Ma per app che richiedono un certo livello di performance (come nel caso di giochi o applicazioni che fanno uso di rendering in 3D) scrivere codice nativo è inevitabile. Per queste ultime situazioni, quindi, abbiamo bisogno di ottimizzare la compilazione.

Se eseguiamo un’app (nativa) compilata solo per ARM, gli scenari possibili sono due:

  • se il dispositivo è basato su architetture ARM, l’eventuale codice nativo sarà eseguito direttamente, senza alcun layer intermedio di virtualizzazione;
  • se il dispositivo utilizza un processore Intel basato su architettura x86, il codice (non essendo stato compilato per quest’ultima architettura) dovrà necessariamente essere virtualizzato, con un conseguente degrado delle prestazioni.

La procedura che consente di compilare un’app per le architetture x86 è, fortunatamente, molto semplice. Utilizzando proprio il sopra citato NDK di Android, tutto ciò che dobbiamo fare è aprire il file jni/Application.mk all’interno di un qualsiasi editor, e modificare la variabile APP_ABI. Quest’ultima, di norma, sarà valorizzata come segue:

APP_ABI := armeabi armeabi-v7a

In questo modo, le architetture di destinazione sono soltanto due: quelle ARM. Se vogliamo aggiungere il supporto alle architetture x86, basta aggiungere la stringa x86 in coda a quella precedente:

APP_ABI := armeabi armeabi-v7a x86

A questo punto, ad ogni compilazione, il file .apk generato conterrà tre versioni dello stesso codice: due compilate per ARM, ed una terza per le architetture x86. La presenza di quest’ultima versione binaria è ciò che consente di aggirare la virtualizzazione dell’app in fase di esecuzione, risultando in un miglioramento (spesso evidente) delle prestazioni.

Prima di presentare qualche ulteriore consiglio per l’ottimizzazione, ci sono però due ulteriori punti da espletare:

  • utilizzo di librerie esterne: se vogliamo utilizzare qualche libreria precompilata, avremo bisogno anche della versione per le architetture x86. È quindi sempre consigliabile l’utilizzo di librerie multipiattaforma o open source, che possano quindi essere compilate anche per l’architettura x86. Tuttavia, se vogliamo gestire la possibilità di compilare librerie diverse in funzione dell’architettura, possiamo sempre modificare il file Android.mk, aggiungendo una condizione simile alla seguente:
    ifeq ($(TARGET_ARCH_ABI), x86)
  • limite sulle dimensioni dell’app: è bene tenere presente che il limite per l’upload delle app su Google Play è di 50 MB. Aggiungere una terza versione del codice può tradursi nel rischio di superare questo limite, a meno che non abbiamo curato attentamente l’aspetto relativo alle dimensioni degli asset grafici e dei contenuti multimediali. È possibile, ad esempio, possibile utilizzare file di espansione che consentono di arrivare fino a 2GB, nei quali possiamo inserire tutti gli assets condivisi e pesanti.

Se vuoi aggiornamenti su Ottimizzare app Android per architetture Intel x86 inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Ottimizzare app Android per architetture Intel x86

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy