跪拜 Guibai
← Back to the summary

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:

  1. Every MethodChannel call incurs additional overhead.
  2. Parameters are serialized into a binary Buffer.
  3. The message must cross the C++ core of the Flutter engine.
  4. On Android, this means it also goes through a JNI call.

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:

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:

  1. Is the channel type correct? Are you using MethodChannel to forcibly simulate a stream, or are you using EventChannel? If you are using MethodChannel to transmit sensor data, encountering an order-of-magnitude latency difference is very normal.

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

  3. 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 Bridge like "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~

Comments

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

GitLqr

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?