Platform Channel VS FFI (Foreign Function Interface) sur Flutter sous Linux

introduction

Flutter, un framework multiplateforme, Il existe un mécanisme appelé Platform Channel pour appeler la fonction native de chaque plateforme depuis l'application. Vous pouvez appeler Java / Kotlin sur Android et Obj-C / Swift sur iOS.

D'autre part, il existe également un mécanisme appelé dart: ffi pour appeler des fonctions C / C ++ depuis l'application. FFI est une abréviation pour Foreign Function Interface, qui est un mécanisme pour appeler le langage C / C ++ à partir de Dart.

Maintenant, Flutter sur Linux fonctionne (actuellement) comme une application GTK. En d'autres termes, le processus appelé par Platform Channel est également décrit en langage C / C ++ (voir ici pour plus de détails).

Par conséquent, les performances lors du traitement de données volumineuses en langage C / C ++ J'ai comparé Method Channel, qui est l'un des canaux de la plate-forme, avec FFI.

Conclusion

Dans les conditions mesurées cette fois, si une conversion de données entre Dart et C est requise, Il n'y avait pas de différence significative entre Method Channel et FFI.

D'autre part, si la conversion des données n'est pas nécessaire, utilisez asTypedList pour FFI. Vous pouvez réduire le nombre de copies de données tout en accédant des deux côtés de Dart / C. Bien entendu, plus la taille des données est grande, plus l'effet est grand, et dans les conditions de mesure cette fois, le résultat était environ 100 fois plus rapide avec FFI.

Au moins si vous avez besoin d'échanger de grandes quantités de données entre Dart-C Il semble préférable de se demander si FFI peut être conçu pour réduire le nombre de copies.

environnement

J'ai expérimenté dans l'environnement suivant. La plate-forme d'exploitation de Flutter est 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)

Résultat de la mesure

Le temps pour memset le tampon sécurisé du côté Dart du côté C / C ++ et le renvoyer du côté Dart a été mesuré. Le programme utilisé pour la mesure est disponible sur ici. J'ai essayé 4 types de mise en œuvre.

--Implémentation 1. Méthode Channel --Implémentation 2. FFI (convertir les données entre Dart-C) --Implémentation 3. FFI (Partager le tampon entre Dart-C en utilisant asTypedList) --Implémentation 4. FFI (hold buffer uniquement au format C)

Les résultats de mesure des quatre méthodes de montage sont les suivants. L'axe horizontal correspond à la taille de la mémoire tampon à définir et l'axe vertical correspond au temps pris (1000 fois en moyenne). Vous pouvez voir que l'implémentation 3 / l'implémentation 4 sans copie des données est nettement plus rapide que l'implémentation 1 / l'implémentation 2 avec copie des données.

release.png

Les moments respectifs où le memset de 8 Mo est terminé sont les suivants. Pour plus de commodité, il est affiché en unités [us], mais je pense qu'il y a une erreur de mesure au moins dans les deux derniers chiffres.

la mise en oeuvre temps[us]
Mise en œuvre 1. Method Channel 23,182
Mise en œuvre 2. FFI (Dart-Convertir les données entre C) 21,616
Mise en œuvre 3. FFI (asTypedListUtilisationdeDart-PartagerletamponentreC) 251
Mise en œuvre 4. FFI (Tenir le tampon uniquement au format C) 261
[référence]Implémentation complète en C 274

Pour référence, le résultat de la version de débogage est le suivant. La mise en œuvre 2 (FFI (avec conversion de données entre Dart-C)) a un temps beaucoup plus long que la version commerciale. On considère que l'AOT du processus de conversion de données décrit dans Dart fonctionne. Comme vous pouvez le voir, cela change quelques fois légèrement, alors n'oubliez pas d'utiliser la version de sortie lors de la mesure des performances avec Flutter. (Vous pouvez démarrer la version finale avec flutter run --release)

debug.png

À la fin

Le résultat était attendu dans une certaine mesure, mais J'étais heureux de pouvoir connaître la asTypedList en l'implémentant, et je pouvais ressentir l'effet de la version finale.

Dans le résultat de la version de sortie, la linéarité est clairement cassée à 512 Ko, mais la raison est inconnue (elle est reproductible). Je pense qu'il est peu probable que mon bug d'implémentation se produise à la fois dans MethodChannel et FFI, mais ... J'aimerais connaître la raison pendant mon temps libre.

Aussi, je ne l'ai pas essayé cette fois, mais je pense qu'il est théoriquement possible d'échanger l'adresse du buffer sécurisé par ffi avec MethodChannel. J'ai déjà implémenté le traitement associé dans MethodChannel, mais certains d'entre eux doivent échanger des données volumineuses. Dans un tel cas, je pense qu'il peut y avoir un tel choix. (Je pense qu'il est nécessaire de se demander si Method Channel est vraiment bon car la multiplate-forme sera perdue)

Flutter sur Linux Desktop est une version alpha, et dart: ffi est une version bêta. Sans parler des performances, l'implémentation côté Plateforme peut changer, alors pardonnez-moi.

référence

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 (Foreign Function Interface) sur Flutter sous Linux
Canaux de plateforme Flutter pour Linux
Désactivez IPv6 sur l'interface réseau dans CentOS Linux 8