react-native-maps / react-native-maps

React Native Mapview component for iOS + Android
MIT License
15.14k stars 4.86k forks source link

Custom markers slow performance with reproduceble demo #2575

Closed compojoom closed 2 years ago

compojoom commented 5 years ago

I was experiencing high CPU usage and lags on the map with what I consider a lot of markers - 400. To my surprise however the map was fast with 300 markers. So, it wasn't really making sense. After debugging this for several hours I managed to come with a reproducible demo of the issue.

https://github.com/compojoom/react-native-maps/tree/high_cpu

launch the examples and switch to google maps as provider and open the "custom markers" example.

in xCode one should see

image

If you go into example/examples/CustomMarkers.js and remove the dsafasdf on line 81 and refresh the example you will see that the CPU usage goes to 1-2%

image

if one changes the width of the custom marker to 100 px for example, then we get again CPU usage of 100%

I've tested this currently only on iOS and I'm not sure if the issue apply to Android.

Environment

"react": "16.5.0", "react-mixin": "^2.0.2", "react-native": "0.57.1", react-native-maps: > 0.21.0 Target Platform: eg: iOS - 12.1 Simulator/iPhone 6

Steps to Reproduce

Use the reproducible demo. The issue is hard to reproduce as one needs a lot of markers and the "correct" styling...

Expected Behavior

I would expect CPU to go down once the markers are rendered

Actual Behavior

CPU stays at 100%

Reproducible Demo

https://github.com/compojoom/react-native-maps/tree/high_cpu

rborn commented 5 years ago

@compojoom nice research, could you please update the issue to follow the template? Thanks

compojoom commented 5 years ago

updated

cklinx commented 5 years ago

Try to set tracksViewChanges={false} in your markers

compojoom commented 5 years ago

@cklinx - this bug report has nothing to do with tracksViewChanges. If you look at the example code you'll see that tracksViewChanges is already set to false: https://github.com/compojoom/react-native-maps/blob/d60402e2c62f26f3be91023381bdb0cafc9c8318/example/examples/CustomMarkers.js#L73

idumachika commented 5 years ago

i have issue styling my map i want to implement border raduis on my map ,if i add border radius it does work

On Sun, Nov 11, 2018, 13:36 Daniel Dimitrov notifications@github.com wrote:

@cklinx https://github.com/cklinx - this bug report has nothing to do with tracksViewChanges. If you look at the example code you'll see that tracksViewChanges is already set to false: https://github.com/compojoom/react-native-maps/blob/d60402e2c62f26f3be91023381bdb0cafc9c8318/example/examples/CustomMarkers.js#L73

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/react-community/react-native-maps/issues/2575#issuecomment-437666657, or mute the thread https://github.com/notifications/unsubscribe-auth/Ab63W_qMG-C_OykLTlIK4oLKEecaDo01ks5uuBnDgaJpZM4YVD5E .

tomtom94 commented 5 years ago

I raise the same question ;). What's up with this big issue @react-community

AngelVenchev commented 5 years ago

I am facing the same issue. What is going on after the markers have been rendered. If I replace the custom markers with the default ones it works really well. However when I replace the markers with ImageBackgroud and Text inside it, with little to no styling it just starts going slowly.

tomtom94 commented 5 years ago

What about putting the inside of the marker in a react class ??

      <Marker
        key={`marker-${data.id}`}
        coordinate={data.location}
        size={30}
        tracksViewChanges={false}
      >
        <MarkerIconIcomoon
          color={
            this.state.slideIndex === data.id && this.state.displayCarousel
              ? "#fecb2f"
              : "black"
          }
          backgroundColor="black"
          size={50}
        />
      </Marker>

I chose Component instead of PureComponent.

class MarkerIconIcomoon extends Component {
  render() {
    return (
      <IconIcomoon
        name="pin-full"
        color={this.props.color}
        backgroundColor={this.props.backgroundColor}
        size={this.props.size}
      />
    );
  }
}

It seems slightly faster, but my markers takes so much time than IOS to render, the gap is yet huge.

compojoom commented 5 years ago

@tomtom94 - In my demo I'm reproducing this with a Text element. In the app, where I have the problem I have a custom component that renders the contents - View, Text, Icon etc. A custom component doesn't help here. I didn't make a custom component in the demo to simplify things.

tomtom94 commented 5 years ago

Hello guys, the slowness issue isn't anymore an issue for me hihi !!!!

Well it is an easy job, just don't use the props onRegionChange

// onRegionChange={currentRegion => {
//   this.onRegionChange(currentRegion);
// }}

This is what causes the android google map slowness issue

Instead you can just simply use the props onRegionChangeComplete

onRegionChangeComplete={currentRegion => {
  this.onRegionChangeComplete(currentRegion);
}}

Cheers. !!

AngelVenchev commented 5 years ago

Hey, I solved my problem and this could help somebody else too. I ended up using the image prop on the marker component to display whatever custom component I need. In my use-case I was implementing clustering using supercluster, I wanted to display a number of clustered pins. I generated my images from here: https://dummyimage.com - about a hundred. Then a designer converted them to circles with a transparent background automatically with a Photoshop action and I loaded them in my application. 100 images were as small as 60kB so it's not a big hit that I have them all in the app.

I know it's not a solution to this particular issue, but it's a temporary workaround until custom markers start working properly

Balasnest commented 5 years ago

@compojoom Did you manage to get it to work? I am also facing the same issue. After using for a while, android maps are slow, lagging. Zoom in/out are very rough too.

tracksViewChanges={false} doesn't help in android. Still the same problem.

Scenario:

  1. Plot all the custom markers ~ 40 (Image, Text) at first.
  2. On marker selection, do an API call and update with new markers in the map.

What would be the issue? Any workaround?

darran-kelinske-fivestars commented 5 years ago

We are noticing significant android performance issues with around 20 custom markers. Has anyone found any solutions/workarounds?

mlop113 commented 4 years ago

We are noticing significant android performance issues with around 20 custom markers. Has anyone found any solutions/workarounds?

I have same problem, CPU is overload 100%, only on IOS

darran-kelinske-fivestars commented 4 years ago

Solution: Native development

This did help us a little though:

tracksViewChanges={false}

mlop113 commented 4 years ago

As @compojoom said this bug report has nothing to do with tracksViewChanges, It is already set to false. It is a year, and we don't have answer or solution It is too bad

woodybury commented 4 years ago

Any updates on this issue? I am experiencing the same: cpu spikes with just a handful of custom markers and callouts(text only).

100% cpu in iOS using the google provider map. Switching to apple maps fixes the performance issue, but is not preferred.

Tried both tracksViewChanges=false and using onRegionChangeComplete, both did not help with google maps on iOS.

elisegriset92 commented 4 years ago

Hello, has anyone found a solution regarding the custom marker making the app really slow (android only) Indeed when I test with the google map marker it's really fast !

stanleyness commented 4 years ago

Bump! Please fix

KeystoneScience commented 4 years ago

bump

hmust92 commented 3 years ago

bump

valeriik commented 3 years ago

My steps:

  1. Launch app with PROVIDER_GOOGLE on iOS without any markers etc, just the map. CPU about 100%
  2. Add 1-5 custom marker(s). CPU about 65%
  3. Remove all custom markers - everything is fine. CPU about 2%

Also:

  1. I tried to use image prop instead of custom marker - the same result - at start CPU about 100%, after all custom markers were removed - CPU about 65%
  2. I tried to use icon prop - everything is fine, if I do not moving the map - CPU about 2%

But I cannot use icon prop because I really need to set different width/height depends on business logic.

I have: react-native: 0.61.2 react-native-maps: 0.27.1

valeriik commented 3 years ago

As CPU performance is very important bug, I have found only 1 way to avoid it - use icon prop instead of image prop or custom marker.

But here I had to create a set of different png files (1x/2x/3x copies of them) to cover all my needs (of course using custom marker would simplify my work 10 times but it'll veery increase CPU performance...)

So, for me it was very important to know marker height, and I did not find any info how to know which @2x/@3x suffixes app uses, therefore I created next code:

  import { PixelRatio } from 'react-native'
  ...
  const getMarkerImgInfo = () => {
    const pr = PixelRatio.get()
    if (pr >= 3) 
      return { img: require('@/assets/markers/map-marker-3x.png'), height: 150 / pr} // @3...
    else if (pr >= 1.5 && pr < 3) 
      return { img: require('@/assets/markers/map-marker-2x.png'), height: 100 / pr} // 1.5...2.99 @2
    else 
      return { img: require('@/assets/markers/map-marker-1x.png'), height: 50 / pr} // < 1.49 @1
  }
  ...
  console.log("Marker height:", getMarkerImgInfo().height);
  ...
  <MapView
  ...
  >
    <Marker
      ...
      icon={getMarkerImgInfo().img}
    />
  </MapView>

where 50, 100 and 150 is the original size of png files in pixels. So this way marker will be approximately the same size for all devices with different dpi/resolution and react-native-maps will work with normal CPU performance on iOS/Android.

I added only 3 png's but you can add more files. For example if height of x1 png is 50px, for PixelRatio.get() === 0.75 you can create map-marker-075x.png with height 50*0.75=~37px etc, to better match file size to screen dpi size.

philipp-spark commented 3 years ago

problem is icon/image prop cant be used due to this issue .... #3664

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

RamonAcedoM commented 3 years ago

Any news on this?

smccamley commented 3 years ago

I'm also having this issue

RyanTG commented 3 years ago

To add another use case to this: in addition to custom Image and Icon markers resulting in very slow performance on Android, styling the markers using a View also results in slow performance.

For example:

        <View style={{
            width: dotWidthHeight,
            height: dotWidthHeight,
            borderRadius: dotWidthHeight / 2,
            borderWidth: 2,
            borderColor: 'white',
            backgroundColor: 'red'
        }}>
        </View>

Works great on iOS. We opted for a styled View because it's easy and flexible (for dynamically resizing) and feels lightweight.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

valeriik commented 2 years ago

guys, any news here?

JurgenFiGO commented 2 years ago

Still experiencing extreme performance degradation on Android when using custom markers when not setting trackViewChanges to false. Any update on a potential fix or workaround?

salah-ghanim commented 2 years ago

with the new architecture of react-native we can get much better performance and get closer to native performance by avoiding serializing map data (markers).

hopefully with RN supporting typescript for Turbo Modules we can start working on that

4156

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

BrodaNoel commented 2 years ago

Yes @stale... This is still a thing.

So, seems like the new Arch will fix (or get it better). Discussion in https://github.com/react-native-maps/react-native-maps/discussions/4301

I'll be waiting for this on Expo! Thanks for the hard work people!

BrodaNoel commented 2 years ago

BTW, regarding performance issues, I think this issue should be consider: https://github.com/react-native-maps/react-native-maps/issues/4158

Sadly, it's already close.

monholm commented 2 years ago

Lets try and get to the bottom of this. This issue is almost 4 years old at this point, and naturally picked up quite a few comments on the way. Because of this, I will focus on the case put forth by the author, and everything else will have to be tracked down in seperate issues - if not I won't be able to keep track of things.

So the issue to focus on here is abnormally high cpu usage with Google Maps on iOS, using custom markers with tracksViewChanges set to false. If anyone is able to reproduce this issue on v1.1.0, please report back with a minimal reproducible example.

monholm commented 2 years ago

I'm closing for now. If anyone is still experiencing this, please comment with an up to date reproducible example and I'll be happy to re-open :)