Hi there!
I am currently making an app which will have a lot of markers - around 4000 spread across whole country. After some testing, it got obvious that all of this gets super laggy
When I use all 3.5k markers and zoom on area with no markers at all, and start dragging the map, I get ~12 fps, on phisical Android tablet in profile mode
After some debugging, print()ing and Stopwatch()ing, I traced which parts use the most time:
In lib/src/layer/marker_layer.dart -> MarkerLayer -> build(), there is a for-loop that iterates over all given Markerks:
|
for (var markerOpt in markerOpts.markers) { |
The whole thing was taking ~25ms, and with Stopwatch(), I traced which parts of loop use the most time:
// I did it like this:
int sumStep = 0;
for(var i in list){
var w = Stopwatch()..start();
i.someStep();
sumStep += w.elapsedMicroseconds();
w.reset();
// Of course, some precision is lost, because some steps take 1.something microsecond
}
print('Step: $sumStep'); // Summed microseconds
This was taking around 7500 us:
|
var pos = map.project(markerOpt.point); |
This 3600:
|
pos = pos.multiplyBy(map.getZoomScale(map.zoom, map.zoom)) - |
|
map.getPixelOrigin(); |
And the rest around 0:
|
if (!_boundsContainsMarker(markerOpt)) { |
|
continue; |
|
} |
|
|
|
markers.add( |
|
Positioned( |
|
width: markerOpt.width, |
|
height: markerOpt.height, |
|
left: pixelPosX, |
|
top: pixelPosY, |
|
child: markerOpt.builder(context), |
|
), |
|
); |
So I started to dig into .project():
|
CustomPoint project(LatLng latlng, [double zoom]) { |
|
zoom ??= _zoom; |
|
return options.crs.latLngToPoint(latlng, zoom); |
|
} |
|
CustomPoint latLngToPoint(LatLng latlng, double zoom) { |
|
try { |
|
var projectedPoint = projection.project(latlng); |
|
var scale = this.scale(zoom); |
|
return transformation.transform(projectedPoint, scale.toDouble()); |
|
} catch (e) { |
|
return CustomPoint(0.0, 0.0); |
|
} |
|
} |
this.scale() and transformation.transform() don't seem to be expensive - they are only some basic calculations...
So, projection.project:
|
@override |
|
CustomPoint project(LatLng latlng) { |
|
var point = epsg4326.transform( |
|
proj4Projection, proj4.Point(x: latlng.longitude, y: latlng.latitude)); |
|
|
|
return CustomPoint(point.x, point.y); |
|
} |
https://github.com/maRci002/proj4dart/blob/7eb11da840ce21c78c017e0a89ee0332ba5a60e3/lib/src/classes/projection.dart#L152
Okay... this ^ is big, and not even a part of this repo, so I don't think we can do anything about it...
Conclusions
While re-building MarkerLayer (which happens constantly while dragging the map), we are doing some expensive calculations, which slow down the whole map - that is, calculating some position from LatLng
// I didn't dig into pos.multiply (step which was taking 3600us), and I don't really know what it's doing...
I'm fresh into this project and I don't know much about mapping, but it seems like we could somehow cache just the projection, and apply only scale and transformations - since only them really change when you drag the map
(This generally seems related #768, but discussion there got kinda chaotic, not knowing what issue actually was, so I'm making this separate)
Hi there!
I am currently making an app which will have a lot of markers - around 4000 spread across whole country. After some testing, it got obvious that all of this gets super laggy
When I use all 3.5k markers and zoom on area with no markers at all, and start dragging the map, I get ~12 fps, on phisical Android tablet in
profilemodeAfter some debugging,
print()ing andStopwatch()ing, I traced which parts use the most time:In
lib/src/layer/marker_layer.dart->MarkerLayer->build(), there is afor-loopthat iterates over all givenMarkerks:flutter_map/lib/src/layer/marker_layer.dart
Line 130 in f09b193
The whole thing was taking ~25ms, and with
Stopwatch(), I traced which parts of loop use the most time:This was taking around 7500 us:
flutter_map/lib/src/layer/marker_layer.dart
Line 131 in f09b193
This 3600:
flutter_map/lib/src/layer/marker_layer.dart
Lines 132 to 133 in f09b193
And the rest around 0:
flutter_map/lib/src/layer/marker_layer.dart
Lines 140 to 152 in f09b193
So I started to dig into
.project():flutter_map/lib/src/map/map.dart
Lines 417 to 420 in f09b193
flutter_map/lib/src/geo/crs/crs.dart
Lines 26 to 34 in f09b193
this.scale()andtransformation.transform()don't seem to be expensive - they are only some basic calculations...So,
projection.project:flutter_map/lib/src/geo/crs/crs.dart
Lines 450 to 456 in f09b193
https://github.com/maRci002/proj4dart/blob/7eb11da840ce21c78c017e0a89ee0332ba5a60e3/lib/src/classes/projection.dart#L152
Okay... this ^ is big, and not even a part of this repo, so I don't think we can do anything about it...
Conclusions
While re-building
MarkerLayer(which happens constantly while dragging the map), we are doing some expensive calculations, which slow down the whole map - that is, calculating somepositionfromLatLng// I didn't dig into
pos.multiply(step which was taking 3600us), and I don't really know what it's doing...I'm fresh into this project and I don't know much about mapping, but it seems like we could somehow cache just the
projection, and apply onlyscaleandtransformations- since only them really change when you drag the map(This generally seems related #768, but discussion there got kinda chaotic, not knowing what issue actually was, so I'm making this separate)