Replies: 2 comments
-
We are intensively working on a new approach atm. 🤞🏾 |
Beta Was this translation helpful? Give feedback.
0 replies
-
@engamir1 It would be nice to see a working prototype. Personally, I think it is easier to embed Python into Flutter rather than Flutter Engine into Python. Flutter app is a lot more than just an app - it's packaging, libraries, tooling, etc. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
performance bottlenecks in the current architecture. I’ll outline the problem, propose a new architecture to overcome the slowness, provide code snippets, detail the technologies needed, and suggest implementation steps. This builds on our previous discussion about latency in Flet’s command-based, network-driven design.Proposal: New Architecture for Flet to Overcome Performance BottlenecksProblem StatementFlet’s current architecture—where Python sends JSON commands over TCP, UDS, or WebSocket to a Flutter frontend—introduces noticeable latency (~10-50ms per command on localhost, higher remotely) due to:Network Overhead: Every UI update (e.g., page.add()) requires a round trip.Serialization/Deserialization: Converting Python objects to JSON and Dart objects back adds overhead (e.g., json.dumps, json.decode).Redux Processing: Flutter’s appReducer copies state and rebuilds the UI, which scales poorly with complex layouts.Layered Communication: Commands pass through FletSocketServer, FletServer, and appReducer, adding processing time.For example, adding a Text and ElevatedButton in page.add() might take 20ms locally, but this compounds with frequent updates or larger UIs, degrading responsiveness.Proposed Solution: In-Process Flutter with Shared Memory and FFITo eliminate network delays and simplify the stack, I propose embedding the Flutter engine directly within the Python process and using shared memory or Foreign Function Interface (FFI) for communication. This shifts Flet from a server-driven UI (SDUI) model to an in-process, memory-shared model for desktop apps, with a fallback for web.Key Features:Embedded Flutter Engine: Run Flutter inside Python using its embedder API.Shared Memory: Use a memory-mapped structure for controls, avoiding serialization.Direct Event Handling: Call Python functions from Dart via FFI for events.Lean Web Fallback: Use WebAssembly (WASM) or a binary WebSocket protocol for web.Benefits:Latency: Drops from milliseconds to microseconds (e.g., ~1-10µs per update).Scalability: No network or JSON overhead; scales with UI complexity.Simplicity: Removes server and Redux layers for desktop.Trade-offs:Desktop-focused initially; web requires a separate strategy.Increased complexity in embedding and FFI setup.Code Snippets for the New ArchitecturePython (flet_fast.py)import flet as ft
from dart_ffi import DartVM, FlutterEngine # Hypothetical FFI wrapper
import ctypes
Control struct for shared memory
class Control(ctypes.Structure):
fields = [
("id", ctypes.c_char_p),
("type", ctypes.c_char_p),
("value", ctypes.c_char_p),
("size", ctypes.c_float),
("event_callback", ctypes.CFUNCTYPE(ctypes.c_void_p)) # Callback pointer
]
class FastPage:
def init(self, app):
self.app = app
self.controls = []
class FastFletApp:
def init(self, target):
self.vm = DartVM() # Initialize Dart VM
self.engine = FlutterEngine(self.vm) # Embed Flutter
self.target = target
Example usage
def main(page):
counter = ft.Text("0", size=20)
def increment(_):
counter.value = str(int(counter.value) + 1)
page.update()
page.add(counter, ft.ElevatedButton("Increment", on_click=increment))
if name == "main":
ft.app = FastFletApp # Override default app
ft.app(main).run()Dart (fast_flet.dart)import 'dart:ffi' as ffi;
import 'package:flutter/material.dart';
final dylib = ffi.DynamicLibrary.open('fast_flet.so');
final updateControls = dylib.lookupFunction<
ffi.Void Function(ffi.Pointer, ffi.Int32),
void Function(ffi.Pointer, int)>('update_controls');
class Control extends ffi.Struct {
@ffi.Pointer<ffi.Uint8>()
external ffi.Pointer<ffi.Uint8> id;
@ffi.Pointer<ffi.Uint8>()
external ffi.Pointer<ffi.Uint8> type;
@ffi.Pointer<ffi.Uint8>()
external ffi.Pointer<ffi.Uint8> value;
@ffi.Float()
external double size;
@ffi.Pointer<ffi.Void>()
external ffi.Pointer<ffi.Void> eventCallback;
String getId() => ffi.Utf8.fromUtf8(id);
String getType() => ffi.Utf8.fromUtf8(type);
String getValue() => ffi.Utf8.fromUtf8(value);
}
class FastFletApp extends StatefulWidget {
@OverRide
_FastFletAppState createState() => _FastFletAppState();
}
class _FastFletAppState extends State {
List controls = [];
void updateControls(ffi.Pointer ptr, int count) {
setState(() {
controls = List.generate(count, (i) => ptr.elementAt(i).ref);
});
}
@OverRide
void initState() {
super.initState();
updateControls.cast<ffi.Pointer>()..call(ffi.Pointer.fromFunction(updateControls));
}
@OverRide
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: controls.map((c) {
if (c.getType() == "text") {
return Text(c.getValue(), style: TextStyle(fontSize: c.size));
} else if (c.getType() == "elevated_button") {
return ElevatedButton(
onPressed: () => c.eventCallback.cast<ffi.Void Function>()(),
child: Text(c.getValue()),
);
}
return SizedBox.shrink();
}).toList(),
),
),
);
}
}
void main() {
runApp(FastFletApp());
}C Glue (fast_flet.c)#include <flutter_embedder.h>
#include <Python.h>
typedef struct {
char* id;
char* type;
char* value;
float size;
void (*event_callback)();
} Control;
FlutterEngine engine;
Control* controls;
int control_count;
void update_controls(Control* new_controls, int count) {
controls = new_controls;
control_count = count;
FlutterEngineSendPlatformMessage(engine, "update", controls, sizeof(Control) * count);
}
void start_engine() {
FlutterEngineRun(engine, "fast_flet.dart");
}
void join_engine() {
// Wait for Flutter to exit (simplified)
while (FlutterEngineIsRunning(engine)) {}
}Technologies NeededFlutter Embedder API:What: C API to run Flutter in a custom host (https://github.com/flutter/engine).Why: Embeds Flutter in Python.Dart FFI:What: Dart’s Foreign Function Interface (https://dart.dev/guides/libraries/c-interop).Why: Calls C functions and accesses shared memory.Python C API + ctypes:What: Embed C in Python and define structs (https://docs.python.org/3/c-api/).Why: Links Python to Dart and manages memory.Shared Memory:What: mmap or ctypes for cross-language data sharing.Why: Fast control updates without serialization.CMake/Ninja:What: Build tools for compiling C glue code.Why: Integrates Flutter engine and Dart code.Implementation Steps for Flet Core TeamProof of Concept (2-4 weeks):Embed Flutter engine in a Python test app using flutter_embedder.h.Pass a simple Control struct via FFI and render a Text widget.Measure latency vs. current architecture.Define Control Schema (1-2 weeks):Design a C struct for all Flet controls (e.g., Text, ElevatedButton, Container).Map Python ft.Control classes to this schema.Integrate FFI (2-3 weeks):Write Dart FFI bindings to read Control structs.Implement Python callbacks for events via ctypes.Replace Network Layer (3-4 weeks):Refactor flet/app.py to support FastFletApp for desktop.Keep FletSocketServer as a fallback for compatibility.Optimize UI Updates (2-3 weeks):Batch control updates in Python and send them in one FFI call.Use Flutter’s setState efficiently with minimal rebuilds.Web Strategy (4-6 weeks):Explore WebAssembly for Python (e.g., Pyodide + Flutter WASM).Alternatively, optimize WebSocket with binary protocol (e.g., CBOR).Testing and Polish (4-6 weeks):Test across platforms (Windows, macOS, Linux).Benchmark against current Flet (e.g., page.add() latency).Documentation and Release (2-3 weeks):Update Flet docs with new architecture details.Release as an experimental feature (e.g., flet_fast).Total Estimated Time: ~20-28 weeks for a minimal viable version, depending on team size.Why This Matters to FletUser Experience: Faster UI updates improve responsiveness, critical for real-time apps (e.g., games, dashboards).Competitive Edge: Matches native app performance, broadening Flet’s appeal.Maintainability: Simplifies the desktop stack, though web needs separate handling.Suggestion to Core Developer:Start with a desktop-only PoC to validate performance gains.Engage the community for feedback on trade-offs (e.g., complexity vs. speed).Consider this as an optional mode (e.g., ft.app_fast()) alongside the current architecture.Learning Resources for Core TeamFlutter Embedding: https://flutter.dev/docs/development/add-to-appDart FFI: https://pub.dev/packages/ffiPython C API: https://docs.python.org/3/c-api/Book: "Programming Flutter" by Carmine Zaccagnino (Pragmatic Bookshelf, 2021) - Embedding chapter.Video: "Flutter Embedding Tutorial" by Flutter team (YouTube).Next StepsSubmit this proposal via Flet’s GitHub Issues (https://github.com/flet-dev/flet/issues/new) with a summary and link to a gist of the code. Want me to draft a shorter version for submission or refine the code further? What’s your take on this approach?
Beta Was this translation helpful? Give feedback.
All reactions