Zum Inhalt springen

Hong Mong 5 Development Treasure Case Sharing Analysis Frame Rate Issues

HarmonyOS Performance Optimization Treasures: Practical Case Analysis of Frame Rate Issues

Hey, HarmonyOS developers! Today I’m sharing a big discovery from development—there are a bunch of super practical performance optimization cases hidden in the official HarmonyOS documentation! These cases not only solve common dropped frame and stutter issues, but also come with detailed analysis ideas and code refactoring solutions. I’ve organized several high-frequency scenarios, explained with code, to help you thoroughly master smoothness optimization!

1. Long List Scrolling Lag Optimization

Problem Phenomenon:

On the „HMOS World“ homepage, after loading 1000 pieces of data, scrolling becomes increasingly laggy, with a dropped frame rate of 7%.

Analysis Tools:

  1. AppAnalyzer: Detected excessive scroll lag rate (>5ms/s).
  2. Frame Profiler: Trace recording found that the BuildLazyItem method took up 52.7% of the time, and the ArticleCardView component was frequently rebuilt.

Key Code (Before Optimization):

@Component
struct ArticleCardView {
  @Prop item: ArticleData; // Deep copy causes performance loss

  build() {
    Row() {
      // Nested complex layout
      ActionButtonView({ icon: this.item.icon }) // Child component uses @Prop
    }
  }
}

@Component
struct ActionButtonView {
  @Prop icon: Resource; // Deep copy every time parent updates
  // ...
}

Problem Location:

  1. The @Prop decorator deep copies complex objects, causing a surge in component creation time.
  2. List items are not reused, and components are rebuilt every time you scroll.

Optimization Plan:

  1. Component Reuse: Use @Reusable to cache components and reduce rebuild overhead.
  2. Replace @prop: Use @Builder to construct lightweight subcomponents and avoid deep copying.

Optimized Code:

@Reusable // Enable component reuse
@Component
struct ArticleCardView {
  aboutToReuse(params: Record<string, Object>) { // Reuse callback
    this.item = params.item as ArticleData;
  }

  build() {
    Row() {
      ActionButtonBuilder({ icon: this.item.icon }) // Use Builder instead
    }
  }
}

// Use Builder instead of @Component
@Builder
function ActionButtonBuilder(icon: Resource) {
  Button(icon)
    .width(40)
    .height(40)
}

Effect: Dropped frame rate reduced from 7% to 0%!

2. Custom Animation Dropped Frames

Problem Phenomenon:

Handwritten animation logic results in only 63fps (device supports 120Hz).

Problem Code:

computeSize() {
  // Manually calculate properties for each frame (bad example!)
  for (let i = 1; i <= doTimes; i++) {
    setTimeout(() => {
      this.heightSize += deltaHeight;
      this.widthSize += deltaWeight; // Frequent calculations on main thread
    }, i * period);
  }
}

Reason:

Loop calculations block the main thread, making it impossible to complete rendering within 8.3ms (120Hz).

Optimization Plan:

Use the system animation API—GPU automatically interpolates calculations, freeing the main thread.

Optimized Code:

Button('click me')
  .onClick(() => {
    this.widthSize = this.flag ? 100 : 200;
    this.heightSize = this.flag ? 50 : 100;
    this.flag = !this.flag;
  })
  .animation({  // System property animation
    duration: 2000,
    curve: Curve.Linear,
    delay: 500
  })

Effect: Frame rate increased to 116.9fps!

3. Excessive Layout Nesting

Problem Phenomenon:

List items nested with 20 layers of Stack, Measure layout time is excessive.

Analysis Tools:

  1. ArkUI Inspector: Visually view the component tree and locate redundant nesting.
  2. Frame Profiler: FlushLayoutTask takes up more than 70% of the time.

Structure Before Optimization:

@Reusable
@Component
struct ChildComponent {
  build() {
    Stack() {
      Stack() {
        Stack() { /* Nested 20 layers... */ }
      }
    }
  }
}

Optimization Plan:

  1. Remove meaningless nesting and use RelativeContainer to replace multiple Stack layers.
  2. Simplify component styles and merge properties.

Optimized Code:

@Reusable
@Component
struct ChildComponent {
  build() {
    RelativeContainer() { // Use relative layout instead of Stack
      Text(this.item)
        .fontSize(50)
        .margin({ left: 10, right: 10 })
        .alignRules({ top: { anchor: "__container__", align: VerticalAlign.Top } })
    }
  }
}

Effect: Layout time reduced by 60%, smooth scrolling.

4. Time-Consuming Operations on the Main Thread

High-Frequency Pitfalls:

  • Synchronously reading large files in onClick.
  • Real-time data calculation during list scrolling.

Optimization Tips:

// Wrong! Synchronous IO on the main thread
onClick(() => {
  let data = fs.readFileSync('huge_data.json'); // Blocks rendering
})

// Correct approach → Hand off to Worker thread
onClick(() => {
  const worker = new worker.ThreadWorker('workers/io.js');
  worker.postMessage('huge_data.json');
})

Key Principle:

The main thread should only handle lightweight operations: UI updates and gesture responses.

Time-consuming tasks (IO/calculation) should be handed over to Worker or async queues.

5. Other Golden Optimization Suggestions

  1. State Management:
    • Use @ObjectLink instead of @Prop to reduce deep copying.
    • Partial refresh: Use @State variables to control the update range of subcomponents.
  2. List Performance:
    • Tune the cachedCount preload number of LazyForEach (recommended 5~10).
    • For complex list items, use @Reusable + aboutToReuse for reuse.
  3. GPU Load:
    • Reduce overlay of transparent layers (avoid overusing opacity).
    • Match image size to display area to avoid memory waste.

Conclusion

After digging deep into the HarmonyOS documentation, I found that the official docs actually hide a lot of „treasure cases“ for performance optimization. In actual development, frame rate issues are mainly concentrated in main thread blocking, long rendering pipelines, and GPU overload. Make good use of Frame Profiler + ArkUI Inspector, and combine today’s code refactoring ideas to easily achieve a silky-smooth 120fps experience!

Encountered other pitfalls? Feel free to discuss in the comments — and don’t forget to ask questions in the HarmonyOS developer community, the official team responds super quickly!

Let’s work hard on HarmonyOS and be the coolest developers! 💪

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert