Quanto è utile JNI in Android?

3

In java / android possiamo chiamare il codice scritto nel linguaggio c / c ++ per il vantaggio della velocità di esecuzione. Ho sentito della compilation di Ahead Of Time che (per quanto ne so) compila l'intera applicazione al codice nativo durante la sua installazione.

Voglio eseguire alcune operazioni matematiche come compressione, crittografia (non immagini, elaborazione audio o video) per confrontare il potere computazionale dei dispositivi e il cui codice può essere scritto sia in java che in c / c ++.

Il mio dubbio è: dato che tutto il codice java è convertito in nativo in Android c'è qualche uso di JNI / NDK e che cos'è?

Update1: Qui è menzionato:

Unlike Dalvik, ART introduces the use of ahead-of-time (AOT) compilation by compiling entire applications into native machine code upon their installation.

Considera di avere un algoritmo di crittografia (che non usa costrutti specifici della lingua come i puntatori). Che normalmente quando compilato in codice nativo (c / cpp) darà la massima velocità di esecuzione. Ma come citato, se tutto il codice è compilato in nativo al momento dell'installazione di app c'è qualche differenza di prestazioni (velocità) tra il metodo di crittografia (scritto in java) e la (stessa) funzione di crittografia (in cpp).

Voglio conoscere l'approccio migliore per l'implementazione dell'algoritmo di crittografia in Android o in sistemi operativi simili basati su VM.

    
posta pebble 04.11.2017 - 19:49
fonte

3 risposte

3

Supponiamo che non sia solo un'applicazione Android. Supponi che la tua azienda abbia bisogno di applicazioni per Android, iOS, Windows, MacOS e Linux. E c'è una funzionalità condivisa. Che è scritto in una lingua disponibile su tutte le piattaforme, cioè C ++.

Ora puoi scegliere di riscrivere una parte enorme della tua applicazione in Java (e Objective-C o Swift e C #, e qualunque sia la moda in Linux), che sarà molto costoso e un incubo di manutenzione, o usando il codice C ++ usando JNI.

    
risposta data 05.11.2017 - 00:03
fonte
1

Ci sono alcuni motivi per cui JNI è utile:

  • Utilizza già costruito o condividi librerie C ++
  • Generalmente si ritiene che C ++ possa offrire prestazioni migliori rispetto a quanto verrà interpretato dal codice bytecode Java. Con C ++ hai un controllo più preciso sull'uso della memoria e puoi essere più deliberato per ottenere alte prestazioni.
risposta data 05.11.2017 - 20:45
fonte
1

My doubt is: since all the java code is converted to native in android is there any use of JNI/NDK and what is it?

Il controllo sulla memoria è il più grande per me. Ho visto Java fare un lavoro molto competente di assegnazione dei registri e selezione delle istruzioni, ma c'è una evidente difficoltà per le prestazioni, e questo è il sovraccarico associato agli oggetti e la perdita che ti dà il layout della memoria e i modelli di accesso. Tuttavia, puoi rendere il codice Java molto più performante del solito e recuperare gran parte del controllo perduto se puoi appoggiarti più pesantemente su semplici vecchi tipi di dati e non su oggetti.

Ad esempio, in C puoi fare cose come questa:

struct Vector
{
    // AoS
    float xyzw[4];
};

E crea una matrice di questi ed assicurati che i contenuti saranno contigui con un passo che è sempre sizeof(struct Vector) che generalmente escluderà padding in questo caso e sarà solo sizeof(float)*4 o esattamente 128 bit. È inoltre possibile eseguire l'heap dell'allocazione allineata ai limiti di 128 bit e quindi essere in grado di utilizzare le mosse allineate nei registri SIMD e di vettorializzare il codice con intrinseche efficienti. Una cosa simile in C ++ in cui è possibile creare una classe vettoriale con metodi e non pagare alcun overhead per comodità e garantire comunque che una serie di essi sia contigua.

Tuttavia, se provi a creare una classe Vector in Java, non ottieni alcun controllo di questo tipo, ogni oggetto Vector avrà alcune meta informazioni aggiuntive associate a cose come reflection e dynamic dispatch che gonfieranno le dimensioni di a Vector . Se provi a creare un array di questi, sarà simile alla creazione di un array di puntatori, a quel punto dovrai pagare memoria aggiuntiva e costi indiretti dei puntatori in cima ai metadati della classe per ogni istanza Vector , e i contenuti dell'array non sarà garantito che sia contiguo (probabilmente sarà inizialmente se allocate ogni singolo Vector in sequenza tutto in una volta, ma dopo il primo ciclo GC, possono essere frammentati in memoria). Quello può essere un killer delle prestazioni con la perdita della località temporale e soprattutto spaziale, che porta a molti più errori di cache del necessario.

Detto questo, spesso c'è molto spazio per il codice Java per andare molto più velocemente. Se si lavora con un gigantesco array di float , ad esempio, invece di un array di Vector , si evita tutto il sovraccarico sopra e si può garantire che il contenuto dell'array rimanga contiguo. In realtà penso che molte persone stiano a rendere le loro applicazioni Java molto performanti senza raggiungere il JNI se solo potessero lavorare con array di semplici vecchi tipi di dati, non di oggetti, per le aree che sono tentate di implementare in JNI. Per comodità puoi creare una classe Vectors che memorizza un gruppo di vettori contemporaneamente (l'overhead degli oggetti sarà quindi banale se è pagato solo una volta per cento vettori, ad esempio, e non per vettore) e fornisce operazioni su di essi, ma internamente rappresenta solo quei vettori come un grande array di float .

Ho persino visto un ragionevole tracciatore interattivo del percorso della CPU implementato in Java (nessuna chiamata API nativa per il tracciamento del percorso stesso, incluso BVH). È stato sorprendentemente veloce, soprattutto per un giovane progetto amatoriale da un uomo, ma quando ho guardato il codice sorgente, è esattamente quello che ha fatto. Evitava oggetti per dati caldi critici dal punto di vista delle prestazioni a favore di matrici giganti di semplici vecchi tipi di dati. Evitava anche di usare Vector e Matrix oggetti, usando solo matrici di float e intervalli di indice. Ovviamente l'implementazione non era così carina e assomigliava molto al vecchio codice C non strutturato, ma era solo per i percorsi e i dati critici di basso livello a cui si accedeva miliardi di volte. La parte di alto livello dell'applicazione era ancora modellata con oggetti. I loro dettagli di implementazione, tuttavia, li hanno evitati.

    
risposta data 01.12.2017 - 12:19
fonte

Leggi altre domande sui tag