Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[expo-image] Multi-second startup stall on low-end Android #25201

Closed
gaearon opened this issue Nov 3, 2023 · 3 comments · Fixed by #25267
Closed

[expo-image] Multi-second startup stall on low-end Android #25201

gaearon opened this issue Nov 3, 2023 · 3 comments · Fixed by #25267
Assignees
Labels
needs review Issue is ready to be reviewed by a maintainer

Comments

@gaearon
Copy link
Contributor

gaearon commented Nov 3, 2023

Minimal reproducible example

https://github.com/bluesky-social/social-app/tree/expo-bug-image-stall-repro

git clone https://github.com/bluesky-social/social-app.git
cd social-app
git checkout expo-bug-image-stall-repro

yarn
yarn prepare -p android
yarn android --device --variant release

This might look like a huge repo but the entire thing is in src/App.native.ts. Ignore other files.

Summary

Rendering even a single expo-image on initial render stalls the startup time on low-end Android by ~4.5 seconds.

I'm testing on Samsung Galaxy A12.

With expo-image

import React, {useEffect} from 'react'
import {Image} from 'expo-image'
import * as SplashScreen from 'expo-splash-screen'

SplashScreen.preventAutoHideAsync()

export default function App() {
  // init
  useEffect(() => {
    SplashScreen.hideAsync()
    console.log('hiding splash')
  }, [])

  return (
    <Image
      style={{
        flex: 1,
      }}
      source={{
        uri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/IMO_9811000_EVER_GIVEN_%2809%29.JPG/800px-IMO_9811000_EVER_GIVEN_%2809%29.JPG',
      }}
    />
  )
}

It takes eight seconds to see any content:

before.mov

This is a production build.

With RN Image

import React, {useEffect} from 'react'
import {Image} from 'react-native' // <-- I only changed this line
import * as SplashScreen from 'expo-splash-screen'

SplashScreen.preventAutoHideAsync()

export default function App() {
  // init
  useEffect(() => {
    SplashScreen.hideAsync()
    console.log('hiding splash')
  }, [])

  return (
    <Image
      style={{
        flex: 1,
      }}
      source={{
        uri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/IMO_9811000_EVER_GIVEN_%2809%29.JPG/800px-IMO_9811000_EVER_GIVEN_%2809%29.JPG',
      }}
    />
  )
}

Bam, it shows content immediately (okay, in two seconds):

after.mov

Environment

expo-env-info 1.0.5 environment info:
System:
OS: macOS 13.2.1
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 18.16.0 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 9.5.1 - /usr/local/bin/npm
Watchman: 2023.10.23.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.13.0 - /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.4, iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4
IDEs:
Android Studio: 2022.1 AI-221.6008.13.2211.9514443
Xcode: 14.3.1/14E300c - /usr/bin/xcodebuild
npmPackages:
@expo/webpack-config: ^19.0.0 => 19.0.0
expo: ^49.0.8 => 49.0.8
react: 18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
react-native: 0.72.5 => 0.72.5
react-native-web: ~0.19.6 => 0.19.8
Expo Workflow: bare

@gaearon gaearon added the needs validation Issue needs to be validated label Nov 3, 2023
@expo-bot expo-bot added needs review Issue is ready to be reviewed by a maintainer and removed needs validation Issue needs to be validated labels Nov 3, 2023
@lukmccall
Copy link
Contributor

Hi @gaearon, thanks for reporting this issue. We are actively working on finding a solution and will keep you informed of any updates.

@lukmccall
Copy link
Contributor

Just wanted to give a quick update on the progress. I have identified the root cause of the slow boot time and developed some easy fixes. Currently, 4 PRs have been created, and with these changes, the startup time should be much smoother. Although the react-native version still seems a bit faster, I will continue working on it to ensure the difference becomes unnoticeable.

lukmccall added a commit that referenced this issue Nov 9, 2023
# Why

Fixes #25201.

# How

I discovered that the previous solution to load `declaredMemberProperties` in the background is not always effective. On low-end devices, this approach can be slower due to the background thread's limited speed. When we need to initialize the view, two threads - the main and the background - attempt to deserialize the Kotlin metadata annotation, leading to poor performance (there is a mutex that forces the main thread to wait for the background job). To resolve this issue, I needed to alter the logic for validating event dispatchers.

> Note: There will be one more PR that aims to improve the boot time on low-end devices. 

# Test Plan

- bare-expo ✅
- [bluesky-social/social-app@expo-bug-image-stall-repro](https://github.com/bluesky-social/social-app/tree/expo-bug-image-stall-repro?rgh-link-date=2023-11-03T04%3A28%3A07Z) ✅
@gaearon
Copy link
Contributor Author

gaearon commented Nov 9, 2023

Thank you!!

lukmccall added a commit that referenced this issue Nov 17, 2023
Fixes #25201.

I discovered that the previous solution to load `declaredMemberProperties` in the background is not always effective. On low-end devices, this approach can be slower due to the background thread's limited speed. When we need to initialize the view, two threads - the main and the background - attempt to deserialize the Kotlin metadata annotation, leading to poor performance (there is a mutex that forces the main thread to wait for the background job). To resolve this issue, I needed to alter the logic for validating event dispatchers.

> Note: There will be one more PR that aims to improve the boot time on low-end devices.

- bare-expo ✅
- [bluesky-social/social-app@expo-bug-image-stall-repro](https://github.com/bluesky-social/social-app/tree/expo-bug-image-stall-repro?rgh-link-date=2023-11-03T04%3A28%3A07Z) ✅
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs review Issue is ready to be reviewed by a maintainer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants