That 150ms Flutter Sensor Latency Is a Channel Misuse, Not a Framework Limit
Welcome to follow the WeChat public account: FSA Full Stack Action 👋
I. Background
Recently, I came across a technical article about why an engineering team decided to abandon Flutter in favor of Kotlin Multiplatform (KMP). The article was very well-written, with detailed migration records, timelines, and code examples, making it highly persuasive.
However, there was one core conclusion in it that I strongly disagree with. They claimed that because the latency for Flutter to process sensor data is approximately 150ms, while native Kotlin takes only 5ms, Flutter has a "physical limit" when handling real-time data.
My first reaction after reading it was not "Is Flutter really this slow?" but rather "This data must conceal a very typical implementation error."
I have deployed the exact same bridging solution in a production environment, handling continuous hardware data streams, and measured P95 latency within 10ms. So, I want to discuss why this 150ms figure likely reflects developer misuse, rather than the framework's performance ceiling.
II. Why 150ms Is Not Flutter's Limit?
Flutter's Platform Channel is essentially a message bus, not a rendering technology.
The most commonly used MethodChannel is actually designed for a "transactional" request-response pattern. The logic is simple: you ask the native side a question, it gives you an answer, and that's it.
The problem is that many tutorials treat MethodChannel as the default means for moving data, including continuous streams like sensor data. This leads to very severe performance overhead:
- Every
MethodChannelcall incurs additional overhead. - Parameters are serialized into a binary
Buffer. - The message must cross the
C++core of theFlutterengine. - On
Android, this means it also goes through aJNIcall.
If you only call it occasionally, these overheads are negligible. But if sensor data is sent dozens of times per second, each data transmission repeats the serialization and thread-switching costs described above. If this data is also dispatched on the native main thread by default, the accumulated latency will definitely look terrible.
To put it bluntly, the 150ms latency is not because the Flutter architecture is slow, but because you are using MethodChannel as a "pipe."
We can compare the differences between the two channel modes when handling streaming data:
| Dimension | MethodChannel |
EventChannel |
|---|---|---|
| Use Case | Single request-response | Continuous streaming data |
| Transmission Overhead | High (full serialization/deserialization per call) | Low (maintains a single open stream) |
| Control Logic | Bidirectional triggering, suitable for transactions | Native side controls sending pace, suitable for data push |
| Performance | Frequent calls cause significant latency accumulation | Suitable for high-frequency, low-latency data stream transmission |
III. How to Achieve Single-Digit Millisecond Latency?
To achieve single-digit millisecond latency, the solution is not to change the language, but to change the "channel type" and "threading model." This is standard usage in the Flutter documentation, not some secret trick.
The core ideas are as follows:
1. Use EventChannel
EventChannel is specifically designed for continuous data streams from native to Dart. It does not need to go through the "request-response" process every time, but instead maintains a persistent stream.
2. Switch the Threading Model
Do not read sensor data on the native main thread! This is the easiest pitfall to fall into. You should:
- Perform sensor reading work on a native background thread.
- Emit data through
EventChannelwith the lightest possible weight. - Consume it as a
Streamon theDartside.
Following this pattern, the P95 latency I previously achieved in a production environment was under 10ms. You do not need to abandon Flutter at all; you just need to realize that MethodChannel is simply not the right tool for handling continuous streams.
IV. Before Deciding to Migrate to KMP, Check These Three Points
I am not saying that team's decision to migrate to KMP was wrong. If a project's core logic is highly dependent on hardware drivers, or if the team is more familiar with KMP, then migration is reasonable.
But if a team concludes that "Flutter cannot handle real-time hardware work" simply because they saw a "sensor latency of 150ms" figure, that is very dangerous. Such a wrong conclusion will mislead other engineers who are evaluating Flutter.
Before deciding to undertake a major refactoring, be sure to check the following three details first:
Is the channel type correct? Are you using
MethodChannelto forcibly simulate a stream, or are you usingEventChannel? If you are usingMethodChannelto transmit sensor data, encountering an order-of-magnitude latency difference is very normal.Where is the thread running? Is the reading work on the native side happening on the main thread or a background thread? If it is executing reads synchronously on the main thread, no matter how fast the channel is, the measurement results will suffer severe latency due to the main thread's load.
Is there throttling on the native side? The raw sampling frequency of sensor data is often much higher than the needs of UI rendering. If you directly dump all the raw data into the
Bridgelike "opening a floodgate," performance will certainly be terrible. Throttling on the native side according to actual needs is key to ensuring performance.
If you have done all three of these things and still hit a hard performance wall that Flutter cannot break through, then considering KMP or native development at that point is the real "truth."
If the article has been helpful to you, please do not hesitate to click and follow my WeChat public account: FSA Full Stack Action, this will be the greatest encouragement to me. The public account has not only Android technology, but also articles on iOS, Python, etc., possibly covering the skill points you want to know about~
Top 2 of 4 from juejin.cn, machine-translated. The original thread is authoritative.
That article claiming 150ms—I feel there's definitely something wrong with it. Unless the data volume is huge, the pure native-to-Flutter latency using MethodChannel—there's no official figure, but it can definitely be done in a few milliseconds.
You can refer to this https://github.com/descosmos/jnigen_benchmark/tree/master
Yes, the tech team behind that article didn't handle Flutter's processing of sensor binary data properly, and then jumped to the wrong conclusion that Flutter couldn't do it.
So if it's parsing a large string, is it still very slow?