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

MapView freezes for 10 seconds when activity start for first time #241

Closed
shm-original opened this issue Sep 16, 2018 · 40 comments
Closed

Comments

@shm-original
Copy link

shm-original commented Sep 16, 2018

It seems loading Native library stop the main thread and make the whole app freeze for a few seconds. This could be annoying when user need to open and close map activity continuously. Is there a way to make the mapView loading process smoother?

profiler

@mtehver
Copy link
Contributor

mtehver commented Sep 17, 2018

Is this specific to a device or are you seeing it on a wide variety of devices? 10 seconds is way too much. Initializing a vector tile baselayer may take a second or even two on slower devices, but not more.

@carlos-mg89
Copy link

I'm experiencing a very similar issue with a second layer I've added in my app. With the previous one, everything is working fine, and the activity opens quite fast. But at the moment I've added the second layer the activity freezes for about 5-10s (haven't measured it).

Quite strangely, it only happens under some weird circumstances. Actually I'm working to add not 1, but 2 additional layers, and only one of them is producing this strange wait of 5-10s.

This are the details:

VectorTileLayer details
The VectorTileLayer is being styled in the following way (I've followed an example from this issue #174):

String contourCSS = "#land-polygons {\n" +
                "polygon-fill: #FFFFFF;\n" +
                "polygon-opacity: 1.0;\n" +
                "}";
contoursVectorLayer = new VectorTileLayer(
    getContourOnlineMBTileDataSource(),
    new MBVectorTileDecoder(new CartoCSSStyleSet(contourCSS))
);
mapView.getLayers().add(contoursVectorLayer);

I've tried commenting the last line, and the app doesn't get freezed when I do that. And I can see the basemap (since it was added before this new layer).

The layer is styled almost as I want to, but before I see the MapView on the screen, it takes 5-10s.

RasterTileLayer details
This layer is loaded almost instantly, as without any issues and/or wait.

SDK version
I'm using the 4.1.3 version of the SDK.

@mtehver
Copy link
Contributor

mtehver commented Sep 22, 2018

@shm-original @carlos-mg89 Thanks for reporting this, but I think I need a minimal demo app to investigate these issues further. I suspect these may be two different issues.

Regarding MapView constructor taking several seconds to load - if you have a valid Carto license, I suggest calling MapView.registerLicense before anything else. I am not sure it will fix the issue, but that is something SDK assumes is done first.

@shm-original
Copy link
Author

shm-original commented Sep 23, 2018

Is this specific to a device or are you seeing it on a wide variety of devices? 10 seconds is way too much. Initializing a vector tile baselayer may take a second or even two on slower devices, but not more.

I guess loading native c++ library taking much time. i encounter this issue on my nexus 5x and on every device which has android 5.x.x(even carto-mobile sample app has this issue in my devices too). on every device map view inflating time is different. i guess my issue does not related to initializing vector layer, because this issue happens to me when the map view inflating for first time without any layer.

@mtehver
Copy link
Contributor

mtehver commented Sep 25, 2018

Thanks for the feedback. I will investigate this further, it could be related to static initialisation in the SDK.

@carlos-mg89
Copy link

I have found out what was the issue with my buggy VectorLayer (I refresh yourselves that my base VectorLayer was working perfectly fine, no delay on the loading time).

When I added a second VectorLayer, that is intended to draw the Contours (more info here https://cloud.maptiler.com/data/contours/#10/47.0879/8.4773 ), the app froze for about 10s. And it started to download an insane number of tiles (here was the clue).

Somehow, I've just realized about this, and manually restricted the MapRange where the Contours layer is supposed to be visible (and therefore to request tiles).

Even though I had set the minZoom value while constructing the HTTPTileDataSource, it was requesting the tiles. My app starts at zoom level 7, but it was requesting tiles from level 9 for the Contours layer. The thing is that since the map is bigger, there is way many more tiles from level 9, but they are requested with the zoom level 7. So there's an insane number of tiles being requested, and that froze the screen (black screen).

This is the code I was using:

private TileDataSource getContourOnlineMBTileDataSource() {
        return new HTTPTileDataSource(
                9,
                14,
                "https://maps.tilehosting.com/data/contours/{z}/{x}/{y}.pbf?key=" + MapApplication.MAPTILER_API_KEY
        );
    }

contoursVectorLayer = new VectorTileLayer(
                getContourOnlineMBTileDataSource(),
                new MBVectorTileDecoder(new CartoCSSStyleSet(contourCSS))
        );

So I added the restriction of the VisibleZoomRange right after I instantiated the Contours layer, and before I added it into the MapView. Like this:

contoursVectorLayer.setVisibleZoomRange(new MapRange(9,24));

I thought that since the HTTPTileDataSource had 9 as a minZoom value, the layer wouldn't have started requesting tiles until it reached that level. If it's not a bug, I believe it should be.

@mtehver
Copy link
Contributor

mtehver commented Sep 27, 2018

@carlos-mg89 Thanks for the explanation. From the SDK side, this is the intended behaviour - SDK always respects the min/max zoom of data source and selects the best matching tiles from the supported range.

@carlos-mg89
Copy link

carlos-mg89 commented Sep 27, 2018

Probably it works as you intended, but if the difference is too big between the supported range (the minimum range in my HTTPTileDataSource is 9 for this case of the Contours) and the actual zoom, then the amount of tiles that the device will request could paralyze and/or freeze the device.

You could give a try to check my code, you only need a valid MapTiler API key (which is free).

I don't think that even you planned the SDK to behave like this, as you said a few days earlier, "10 seconds is way too much." for initializing/adding a Layer to the MapView. Don't you think?

Perhaps you could optimize the code, and if the difference between the minZoom set in the HTTPTileDataSource and the actual zoom is equal to 1, then you could request the tiles. But in my experience, requesting them with a difference of 2 in the zoom level, for vector tiles, it's way too much resources (not for Raster, since I'm having a similar setup for another Raster layer and it works fine).

My trials were done with a real Samsung Galaxy S6 and an x86 VM with 3GB of RAM. So it wasn't like a low specs device/VM.

@jaakla
Copy link
Contributor

jaakla commented Sep 27, 2018

Why do you want to use 9 as layer data minzoom? Usually it is same as visible zoom range minimum, or just 0. This would avoid such issues.

@carlos-mg89
Copy link

On the MapTiler documentation page, for the contours dataset, 9 is the minimum zoom level:
https://cloud.maptiler.com/data/contours/#10/47.0879/8.4773

I don't want to restrict the minimum zoom level, in the app, since it's useful for the user to go to zoom levels < 9. However, as I've explained, setting up the VisibleZoomRange in this layer solved my problem. If it's useful for you, then great. Otherwise, on my side, the issue is solved and the app gets loaded as fast as it was being loaded before.

Thanks!

@jaakla
Copy link
Contributor

jaakla commented Sep 27, 2018

Yes, for this case VisibleZoomRange for Layer is correct setting, and Data Source zoom range is not the right one. There are several zoom ranges to be set, so I understand it can be confusing.

@farfromrefug
Copy link
Contributor

I am also seeing some pretty long app start /activity start.

I am using the android samples app and the AdvancedMapAndroid project.

  • The app takes around 5s to load if not more on a a3 2017.
  • if i comment the registerLicense from MapApplication the main activity started instantly.
  • Any example activity takes around 3s still to load and show the map

If i compare this to Mapbox which uses the same CPP lib / JNI method, there is almost no loading time. You can test this with the Mapbox demo app.

I really think this should be investigated. As @shm-original noted this can be a big problem for maps app which can be quickly and often open/close

@jaakla
Copy link
Contributor

jaakla commented Oct 14, 2018

@farfromrefug what is exact SDK version? The registerLicense does online request to our license server, can you monitor networking to see if there is something stuck ?

@farfromrefug
Copy link
Contributor

@jaakla i tried with 4.1.3 and 4.1.4-rc.1.
Here is a systrace. I don't see anything related to network. Seems like it's in the c lib which i can't seem to trace
mynewtrace.html.zip

@mtehver
Copy link
Contributor

mtehver commented Oct 15, 2018

@farfromrefug Thanks for the feedback. I ran some tests on Pixel 2, and got the following results:

  • SDK initialization (loading the native part) in the first MapView call takes about 700ms
  • CartoOnlineVectorTileLayer takes additional 500ms using 4.1.3 version (4.1.4 reduces this to 400ms)

So, in total about 1.1-1.2s. Most Android devices are slower, by about 1.5-2x. So we are talking about 2-2.5s range. We will likely take a closer look at the native part in the near future, perhaps something can be optimized there.

@mtehver
Copy link
Contributor

mtehver commented Oct 15, 2018

A small note about the request to license server Jaak mentioned above - this is done in background thread and does not block any calls. It may delay displaying the base map layers a bit, though.

@farfromrefug
Copy link
Contributor

@mtehver i understand that it may depends on the phone. An a3 is not that bad and it seems strange.
What bugs me is the difference with Mapbox. And i am not sure i was seeing that before.
I will test on another A3 because mine is rooted.

Do you of any way to systrace what is happening in the C lib?

@farfromrefug
Copy link
Contributor

farfromrefug commented Oct 15, 2018

@mtehver i tested on a A3 with no modification and i have the same issue. Will test on my tablet to see how it goes.

EDIT: I see 2 issues in fact:

  • opening app, native lib is loaded. This takes a long time
  • open a map activity. Takes around 3 secs

I think the 2 are very different.
About the second one, could it be related to zip style processing? When i was working on my custom style, i was seeing a lot of time spend on zip processing.

@farfromrefug
Copy link
Contributor

@mtehver Some news i have been making some new tests.

And what i realized about the map activity opening is that i see an issue with Online Base Maps example from the Advanced Map app on the play store.
Other examples seems to be a lot faster (geocoding is instant).

So might be something with that activity.

My issue is that i cant find the sample code.

https://github.com/CartoDB/mobile-android-samples seems pretty old, kotlin and native are different and i don't have the same examples.

Is there any way to get the code from the play store app? That would help a lot

@jaakla
Copy link
Contributor

jaakla commented Oct 16, 2018

The play store code could be in 'dev' branch of same repo. There is no really another source for it.

@farfromrefug
Copy link
Contributor

@jaakla cant find the same samples.
For example i cant find 3D City that i have in the play store version

@jaakla
Copy link
Contributor

jaakla commented Oct 16, 2018

Can you give screenshot what do you exactly mean? Some Android apps are done with dotnet and are in https://github.com/CartoDB/mobile-dotnet-samples

@farfromrefug
Copy link
Contributor

@jaakla you are right that must the dotnet version!
https://github.com/CartoDB/mobile-dotnet-samples/blob/master/AdvancedMap.Droid/Main/Samples.cs

There are in the same order

However if you install the Advanced Samples on android you'll see that the last sample is "3D City" (sorry cant get the screenshot right now). That's the only one missing in dot net sample!
Kind of a mystery!

But thanks i will copy the dotnet version to create my Nativescript sample app. Already a few samples running

@jaakla
Copy link
Contributor

jaakla commented Oct 16, 2018

I checked this, it is correct that 3D city is not published as the data is not publicly available. If you want to get similar things, then general approach is that you need data in special NMLDB format and then add specific layer with NMLModelLODTreeOnlineDataSource to the map. We have converter from KMZ to own format https://github.com/CartoDB/mobile-sdk/wiki/NML-converter . Specific sample is done using TomTom 3D city data, and it can be licensed from them.

@farfromrefug
Copy link
Contributor

@jaakla no issue there. I just wanted to make sure i was having the latest samples to mimic them in my Nativescript implementation

Thanks!

@farfromrefug
Copy link
Contributor

@mtehver i need to bump this one as I am facing it again. I tried to use carto on android wear and I faced the registerLicense call actually hanging the app at boot (without actually initiating a map view).
you said it was running on a background thread, but I cant really check it as the actual code is not open sourced. can you confirm it run in the background even if registerLicense is called in the main thread?

@mtehver
Copy link
Contributor

mtehver commented Mar 28, 2019

@farfromrefug I will try to get an older test device next week and try to reproduce this.

@farfromrefug
Copy link
Contributor

farfromrefug commented Mar 28, 2019

@mtehver just to give some feedback on this. I have just ran some tests because i could really understand why the registerLicense would be so slow. I think it's not the registerLicense per say which is slow. I think it is more the native lib loading.
I think i see it as registerLicense because calling it triggers the native lib loading. I tested that way:

  • Carto dep but no call to Carto sdk in my app: loading takes around 2/3s
  • only call registerLicense in my app: loading takes around 10s
  • only create a mapview without calling registerLicense: loading takes around 10s

So i think it's related to the static loading of the native lib from ui module. Will try and get some profiling from Android Studio.
Also i am trying right now to do the same think with MapBox to see if it just related to native lib loading or more to the Carto Mobile SDK

EDIT: tested with Mapbox and the app takes around 4s to run and show the Mapbox map.
Could it be that you load the native lib the static way, while Mapbox does it the same way as GoogleMap with Mapbox.getInstance() ?

@mtehver
Copy link
Contributor

mtehver commented Mar 29, 2019

@farfromrefug Thanks, appreciate this info. I think slow loading of native part is the most likely reason. A workaround is to launch a background thread and perform 'registerLicense' in this thread. I have not tried it, but this should be safe and if your app does not need to display MapView immediately would hide the long loading time.

@farfromrefug
Copy link
Contributor

@mtehver i might try that. but still it s really long compared to others like Mapbox. Is that something you can look at? if I find time.I might try and look at it. this seems really important to me. especially since it is a 200% increase.
are there operations done on the native side while the native lib gets loaded?

@farfromrefug
Copy link
Contributor

@mtehver tried running the registerLicense in a background thread. It works but does not change anything in the sense that the native lib loading still takes around 4 to 5s!
I have some timeline view which shows the time used.
Screen Shot 2019-04-05 at 10 19 09

@mtehver
Copy link
Contributor

mtehver commented Apr 5, 2019

@farfromrefug Thanks, appreciate this. I have not had time to look closely into this, but will do soon.

@mtehver
Copy link
Contributor

mtehver commented Apr 15, 2019

I have some good news regarding the upcoming release. I measured registerLicense time of SDK 4.1.6 on Pixel 2, and got 760ms. This is far from 10s, but still quite a lot. The upcoming SDK 4.2 reduces this time to 30ms on the same device. This seems to come from switching from gcc to clang/llvm and using newer NDK to compile the SDK.

Also, creating a CartoOnlineVectorTileLayer takes now 270ms instead of 390ms on the older version. This comes probably from the smaller built-in style asset (we will be dropping large fonts from the SDK).

@farfromrefug
Copy link
Contributor

@mtehver Amazing news! About the 10s. It was before i knew better. In the last profiling image you can see that it takes 4s on my A3 2017.
And the Pixel 2 is almost 2 times better than the a3 (mem, cpu ..)

Cant wait to test this!

Thanks

@mtehver
Copy link
Contributor

mtehver commented Apr 30, 2019

@shm-original @carlos-mg89 SDK 4.2.0-rc.1 is now available and should fix this. Keeping this open for a while, though.

@farfromrefug
Copy link
Contributor

I can confirm it is a huge step forward. Need to run some more tests though

@carlos-mg89
Copy link

It had stopped happening to me in after setting the min zoom level correctly while using the contour layers of MapTiler. However, I can confirm that it starts much faster with the 4.2.0RC1. Although I experience much faster loading of Markers / Points on 4.1.6 (I've started testing 4.1.6 and 4.2.0RC1 today). So excellent job with both new releases! 4.2.0 looks promising but it definitely needs some testing.

@mtehver
Copy link
Contributor

mtehver commented May 2, 2019

@carlos-mg89 Can you elaborate a bit how you tested the performance of loading Markers and Points? How many elements did you use? And did you measure the time to add the elements to your data source or something else?

@carlos-mg89
Copy link

I've created a dedicated issue about this matter (the loading time of Points): #282

There you have pretty much all the code involved.

@mtehver
Copy link
Contributor

mtehver commented May 28, 2019

Closing this. This issue refers to multiple subissues. SDK native component loading time has significantly decreased and other issues haved been discussed separately and mostly fixed.

@mtehver mtehver closed this as completed May 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants