Platform Channel VS FFI (Fremdfunktionsschnittstelle) unter Flutter unter Linux

Einführung

Flutter, ein plattformübergreifendes Framework, Es gibt einen Mechanismus namens Platform Channel zum Aufrufen der Native-Funktion jeder Plattform aus der Anwendung. Sie können Java / Kotlin unter Android und Obj-C / Swift unter iOS aufrufen.

Andererseits gibt es auch einen Mechanismus namens dart: ffi zum Aufrufen von C / C ++ - Funktionen aus der Anwendung. FFI ist eine Abkürzung für Foreign Function Interface, ein Mechanismus zum Aufrufen der C / C ++ - Sprache von Dart.

Jetzt funktioniert Flutter unter Linux (derzeit) als GTK-App. Mit anderen Worten, der von Platform Channel aufgerufene Prozess wird auch in der Sprache C / C ++ beschrieben (Klicken Sie hier, um weitere Informationen zu erhalten (https://qiita.com/takeoverjp/items/657954c85cf1ead236c5)).

Daher die Leistung bei der Verarbeitung großer Datenmengen in C / C ++ Ich habe Method Channel, einen der Plattformkanäle, mit FFI verglichen.

Fazit

Unter den diesmal gemessenen Bedingungen, wenn eine Datenkonvertierung zwischen Dart und C erforderlich ist, Es gab keinen signifikanten Unterschied zwischen Method Channel und FFI.

Wenn andererseits keine Datenkonvertierung erforderlich ist, verwenden Sie asTypedList für FFI. Sie können die Anzahl der Datenkopien reduzieren, während Sie von beiden Seiten von Dart / C aus zugreifen. Je größer die Datengröße ist, desto größer ist natürlich der Effekt, und unter den Messbedingungen war das Ergebnis mit FFI diesmal etwa 100-mal schneller.

Zumindest, wenn Sie große Datenmengen zwischen Dart-C austauschen müssen Es scheint besser zu überlegen, ob FFI so gestaltet werden kann, dass die Anzahl der Kopien verringert wird.

Umgebung

Ich habe in der folgenden Umgebung experimentiert. Die Betriebsplattform von Flutter ist Linux.

$ grep 'model name' /proc/cpuinfo | uniq -c
      8 model name	: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
$ grep MemTotal /proc/meminfo 
MemTotal:       32752704 kB
$ uname -a
Linux chama 5.5.8 #1 SMP Sat Mar 7 22:29:22 JST 2020 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -d
Description:	Ubuntu 18.04.5 LTS
$ flutter --version
Waiting for another flutter command to release the startup lock...
Flutter 1.24.0-8.0.pre.143 • channel master • https://github.com/flutter/flutter
Framework • revision e4d94f7ccd (2 hours ago) • 2020-11-07 12:15:22 +0100
Engine • revision 1e3ceb037f
Tools • Dart 2.12.0 (build 2.12.0-27.0.dev)

Messergebnis

Die Zeit, um den auf der Dart-Seite auf der C / C ++ - Seite gesicherten Puffer zu speichern und zur Dart-Seite zurückzukehren, wurde gemessen. Das für die Messung verwendete Programm ist unter [hier] verfügbar (https://github.com/takeoverjp/flutter_linux_bridge_perf). Ich habe 4 Arten der Implementierung ausprobiert.

Die Messergebnisse der vier Montagemethoden sind wie folgt. Die horizontale Achse ist die Größe des Puffers, der gespeichert werden soll, und die vertikale Achse ist die benötigte Zeit (1000-facher Durchschnitt). Sie sehen, dass Implementierung 3 / Implementierung 4 ohne Datenkopie erheblich schneller ist als Implementierung 1 / Implementierung 2 mit Datenkopie.

release.png

Die jeweiligen Zeiten, zu denen ein 8-MB-Memset durchgeführt wird, sind wie folgt. Der Einfachheit halber wird es in [us] -Einheiten angezeigt, aber ich denke, dass zumindest in den letzten beiden Ziffern ein Messfehler vorliegt.

Implementierung Zeit[us]
Implementierung 1. Method Channel 23,182
Implementierung 2. FFI (Dart-Konvertieren Sie Daten zwischen C.) 21,616
Implementierung 3. FFI (asTypedListMitDart-PufferzwischenCteilen) 251
Implementierung 4. FFI (Halten Sie den Puffer nur im C-Format) 261
[Referenz]Vollständige C-Implementierung 274

Als Referenz ist das Ergebnis der Debug-Version wie folgt. Implementierung 2 (FFI (mit Datenkonvertierung zwischen Dart-C)) hat eine erheblich längere Zeit als die Release-Version. Es wird davon ausgegangen, dass die AOT des in Dart beschriebenen Datenkonvertierungsprozesses funktioniert. Wie Sie sehen können, ändert es sich einige Male geringfügig. Vergessen Sie also nicht, die Release-Version zu verwenden, wenn Sie die Leistung mit Flutter messen. (Sie können die Release-Version mit flutter run --release starten)

debug.png

Am Ende

Das Ergebnis wurde bis zu einem gewissen Grad erwartet, aber Ich war froh, dass ich die "asTypedList" durch Implementierung kennen und die Wirkung der Release-Version spüren konnte.

Im Ergebnis der Release-Version ist die Linearität bei 512 KB deutlich gebrochen, der Grund ist jedoch unbekannt (reproduzierbar). Ich halte es für unwahrscheinlich, dass mein Implementierungsfehler sowohl in MethodChannel als auch in FFI auftritt, aber ... Ich möchte den Grund in meiner Freizeit herausfinden.

Ich habe es diesmal nicht versucht, aber ich denke, es ist theoretisch möglich, die Adresse des durch ffi gesicherten Puffers mit MethodChannel auszutauschen. Ich habe bereits eine verwandte Verarbeitung in MethodChannel implementiert, aber einige von ihnen müssen große Datenmengen austauschen. In einem solchen Fall denke ich, dass es eine solche Wahl geben kann. (Ich denke, es muss überlegt werden, ob Method Channel wirklich gut ist, da die plattformübergreifende Funktionalität verloren geht.)

Flutter on Linux Desktop ist eine Alpha-Version und dart: ffi ist eine Beta-Version. Ganz zu schweigen von der Leistung, die Implementierung auf der Plattformseite kann sich ändern. Bitte verzeihen Sie mir.

Referenz

MethodChannel class - services library - Dart API dart:ffi library - Dart API Is it possible to get pointer of Uint8List instead of allocating then copy · Issue #31 · dart-lang/ffi

Recommended Posts

Platform Channel VS FFI (Fremdfunktionsschnittstelle) unter Flutter unter Linux
Flatterplattformkanäle für Linux
Deaktivieren Sie IPv6 auf der Netzwerkschnittstelle in CentOS Linux 8