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
-
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