この記事は、【 可茂IT塾 Advent Calendar 2025 】の20日目の記事です。
FFI (Foreign Function Interface) とは、あるプログラミング言語から、異なる言語で記述された関数やサービスを利用するための仕組みのことです。Flutterにおいては、Dart言語からCやC++、Rustといったネイティブ言語のコードを呼び出す機能を指します。
今回は、RustとDart実装と比較してどの程度「実行速度」が向上するかを計測します。
flutter rust bridgeを使用しました。
flutter_rust_bridge(FRB)は、Flutter(Dart)とRustをシームレスに接続するためのコード生成ツールです。
通常、FlutterからRustを呼び出すには「Dart FFI(Foreign Function Interface)」を使用しますが、これには手動での型変換やメモリ管理など、複雑でボイラープレート(定型コード)の多い作業が必要です。flutter_rust_bridgeはこれらのグルーコード(接着コード)を自動生成し、あたかも「単一の言語」で書いているかのような開発体験を提供します。
V2の導入は非常にシンプルです。前提として、Flutter SDKとRust(Cargo)がインストールされている環境が必要です。
まず、RustのパッケージマネージャーであるCargoを使って、FRBのCLIツールをインストールします。
cargo install flutter_rust_bridge_codegen
以下のコマンドを実行すると、FlutterとRustがセットアップされた新しいプロジェクトが作成されます。
flutter_rust_bridge_codegen create my_app
既にFlutterアプリがある場合は、プロジェクトのルートディレクトリで以下のコマンドを実行します。
flutter_rust_bridge_codegen integrate
これだけで、Rustのセットアップ(クレート作成)や、Flutter側の設定(Android/iOS/CMake等のビルド設定)が自動的に行われます。
導入が完了したら、実際にコードを書いてみましょう。基本的な流れは「Rustを書く」→「コード生成」→「Dartで呼ぶ」の3ステップです。
rust/src/api/ ディレクトリ(または lib.rs から参照される場所)に通常のRustコードを書きます。
// rust/src/api/simple.rs
pub fn hello(name: String) -> String {
format!("Hello, {}! This is Rust.", name)
}
// 複雑な計算などもここに記述
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
開発中は以下のコマンドを実行しておくと、Rustファイルを保存するたびにDart側のコードを自動生成(ホットリロード)してくれます。
flutter_rust_bridge_codegen generate --watch
生成されたコードを使って、Flutter側からRustの関数を通常のDart関数のように呼び出せます。
// lib/main.dart
import 'package:flutter_rust_bridge/flutter_rust_bridge.dart';
import 'src/rust/api/simple.dart'; // 生成されたファイルをインポート
Future<void> main() async {
// 初期化処理
await RustLib.init();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
// ... (省略)
Widget build(BuildContext context) {
return TextButton(
onPressed: () async {
// Rustの関数を呼び出す
final message = await hello(name: "Flutter Developer");
print(message); // "Hello, Flutter Developer! This is Rust."
},
child: const Text("Call Rust"),
);
}
}
ベンチマークでは以下の処理を比較しました:
注意: リリースモードでビルドすることが重要です。デバッグモードでは正確な性能測定ができません。
以下は、軽量・中規模・重量の3種類のMarkdownファイルをDartとRustでそれぞれ1000回パースした結果です。
| Markdown | Size(KB) | 言語 | 試行回数 | 平均時間 | 最大時間 | 最小時間 | 合計時間 |
|---|---|---|---|---|---|---|---|
| 軽め | 0.04 | Dart | 1000 | 0.0ms | 0.2ms | 0.0ms | 43.9ms |
| 中 | 0.40 | Dart | 1000 | 0.2ms | 1.1ms | 0.2ms | 223.1ms |
| 重め | 80.23 | Dart | 1000 | 19.9ms | 22.3ms | 19.6ms | 19891.2ms |
| 軽め | 0.04 | Rust | 1000 | 0.1ms | 1.6ms | 0.0ms | 70.8ms |
| 中 | 0.40 | Rust | 1000 | 0.1ms | 0.8ms | 0.0ms | 74.0ms |
| 重め | 80.23 | Rust | 1000 | 1.3ms | 4.9ms | 1.2ms | 1306.3ms |
分析
画像処理(エッジ検出)のベンチマーク結果です。異なるサイズの画像に対して、DartとRustでそれぞれ処理を実行しました。
| 画像 | Size(KB) | 言語 | 処理時間 |
|---|---|---|---|
| 1 | 38.32 | Dart | 619.3ms |
| 2 | 13971.42 | Dart | 24188.4ms |
| 3 | 8399.16 | Dart | 32782.3ms |
| 1 | 38.32 | Rust | 9.6ms |
| 2 | 13971.42 | Rust | 307.3ms |
| 3 | 8399.16 | Rust | 335.3ms |
分析
ベンチマークリポジトリ: GitHub - flutter_rust_bridge_benchmark
より詳細な情報や最新のAPIについては、公式ドキュメント(https://cjycode.com/flutter_rust_bridge/)を参照することをお勧めします。
可茂IT塾ではFlutter/Reactのインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More可茂IT塾ではFlutter/Reactのインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More