Discovering HarmonyOS Treasures: Practical Guide to Cross-Thread Serialization Performance Optimization
Hello everyone! Today, while browsing the HarmonyOS documentation, I found a super useful tool—the serialization detection feature of DevEco Profiler! When using TaskPool
or Worker
for multithreaded development, I often encounter object cross-thread lag issues. It turns out HarmonyOS has already provided a solution. Below, I’ll combine code and real-world cases to help you master performance optimization!
1. Pain Point: Why Does Cross-Thread Serialization Slow Down Performance?
When objects are passed across threads (e.g., main thread → worker thread), the system will automatically serialize and deserialize them. If the object structure is complex (such as nested arrays or class methods), the time consumption will skyrocket! For example:
// Unoptimized: Passing the entire object
class Book {
title: "string = \"\";"
content: string = "";
authorList: string[] = []; // Array members can be huge!
}
// Main thread passes data to worker thread
taskpool.execute(processBooks, bookList); // Serialization happens here!
Problem: When bookList
contains 50,000 books, serialization may take 260ms+! The main thread gets stuck!
2. Treasure Tool: DevEco Profiler Serialization Detection
1️⃣ How to Enable
- Open DevEco Studio → Profiler → Select Frame template
- Click Record → Operate the app to trigger cross-thread communication
- Stop recording → Check for timeout warnings (red markers) in the
Anomaly
lane
2️⃣ Locate Problematic Code
Select the timeout area → View the ArkTS Callstack
lane → Double-click the call stack to jump to the source code!
3️⃣ Customize Timeout Threshold
Click Options in the Anomaly
lane → Set the threshold (default is 8ms), suitable for different performance requirements:
Profiler.enableSerializationTimeoutCheck(threshold: 5); // Change to 5ms to trigger warnings
3. Optimization Solutions: Sendable Refactoring + Data Slimming
HarmonyOS recommends using Sendable objects (reference passing) instead of serialization, greatly improving efficiency!
✅ Case 1: Book Data Transfer Optimization
Before Optimization (Serialization 260ms):
class Book {
// Non-Sendable object, every field is copied
title: string = "";
authorList: string[] = [];
}
const bookList: Book[] = load50000Books(); // 50,000 books
taskpool.execute(processBooks, bookList); // Stuck on main thread serialization!
After Optimization (<8ms):
// Key: Implement the Sendable interface!
class Book implements Sendable {
// 1. Keep only primitive type fields
title: string = "";
// 2. Avoid complex structures, use reference IDs instead of arrays
authorIds: number[] = [];
// 3. Query data as needed in the worker thread
static async getAuthors(ids: number[]): Promise<string[]> {
return db.queryAuthors(ids); // Worker thread queries the database
}
}
// Main thread only passes necessary data
taskpool.execute(processBooks, bookList.map(b => b.authorIds));
✅ Case 2: Image Processing Optimization
Anti-pattern: Passing image data directly
// Main thread reads image → serializes and passes → worker thread processes
const imageData: ArrayBuffer = readFile("large_image.jpg");
taskpool.execute(processImage, imageData); // May timeout!
Optimization: Pass file path + offset
// Main thread
const imageInfo = { path: "large_image.jpg", offset: 0 };
taskpool.execute(processImage, imageInfo); // Instant completion!
// Worker thread
@Concurrent
function processImage(info: { path: string, offset: number }) {
const buffer = readFileSegment(info); // Worker thread reads the file itself
}
4. Performance Comparison: Immediate Results
Solution | Serialization Time for 50,000 Books | Main Thread Lag |
---|---|---|
Unoptimized (normal object) | 260ms+ | Noticeable lag |
Sendable Refactoring | <8ms | No lag |
File path instead of data | <1ms | No lag |
5. Pitfall Summary
-
Use Sendable whenever possible: Implement the
Sendable
interface for classes, avoid complex structures inside - Data slimming: Pass the minimal data set (such as IDs, paths), let the worker thread query as needed
- Make the tool a habit: Enable Profiler recording during development, regularly check serialization time
- Beware of large objects: Be cautious when passing objects larger than 10KB!
There are many more treasure tools hidden in the HarmonyOS documentation. I recommend checking out the Performance Analysis Documentation~ If you encounter any pitfalls, feel free to discuss in the comments and let’s dig for treasures together! 💪
Next time you encounter cross-thread lag, don’t rush to work overtime—open Profiler and take a look first!
Keep Coding, Write Fewer BUGs! 😉
Top comments (0)