Skip to content

Instantly share code, notes, and snippets.

@ninjaasmoke
Created December 6, 2024 16:08
Show Gist options
  • Save ninjaasmoke/4b80b1f8733a4eef15f93108f6b4fa5a to your computer and use it in GitHub Desktop.
Save ninjaasmoke/4b80b1f8733a4eef15f93108f6b4fa5a to your computer and use it in GitHub Desktop.
a comparison of different implementations for drawing markers on a map
class LatLng {
final double latitude;
final double longitude;
LatLng(this.latitude, this.longitude);
}
class LatLngBounds {
final LatLng southwest;
final LatLng northeast;
LatLngBounds(this.southwest, this.northeast);
bool contains(LatLng point) {
return point.latitude >= southwest.latitude &&
point.latitude <= northeast.latitude &&
point.longitude >= southwest.longitude &&
point.longitude <= northeast.longitude;
}
}
class Marker {
final LatLng position;
Marker(this.position);
}
enum MarkerType { type1, type2, type3 }
class MarkerSource {
final Set<Marker> markers;
MarkerSource(this.markers);
}
Set<Marker> calculateVisibleMarkers1(
LatLngBounds bounds,
Map<MarkerType, MarkerSource> markerSources,
Map<MarkerType, bool> visibility,
Set<Marker> allRenderedMarkers,
) {
final visibleMarkers = markerSources.values
.map((source) => source.markers.where((marker) => bounds.contains(marker.position)))
.expand((element) => element)
.toSet();
for (var type in MarkerType.values) {
if (visibility[type] == true) {
visibleMarkers.addAll(
markerSources[type]?.markers.where((marker) => bounds.contains(marker.position)) ?? {},
);
}
}
allRenderedMarkers.addAll(visibleMarkers);
return visibleMarkers;
}
Set<Marker> calculateVisibleMarkers2(
LatLngBounds bounds,
Map<MarkerType, MarkerSource> markerSources,
Map<MarkerType, bool> visibility,
Set<Marker> allRenderedMarkers,
) {
final visibleMarkers = <Marker>{};
for (var type in MarkerType.values) {
if (visibility[type] == true && markerSources[type] != null) {
visibleMarkers.addAll(
markerSources[type]!
.markers
.where((marker) => bounds.contains(marker.position)),
);
}
}
if (visibleMarkers.isNotEmpty) {
allRenderedMarkers.addAll(visibleMarkers);
}
return visibleMarkers;
}
Set<Marker> calculateVisibleMarkers3(
LatLngBounds bounds,
Map<MarkerType, MarkerSource> markerSources,
Map<MarkerType, bool> visibility,
Set<Marker> allRenderedMarkers,
) {
final visibleMarkers = <Marker>{};
markerSources.forEach((type, source) {
if (visibility[type] == true) {
visibleMarkers.addAll(
source.markers.where((marker) => bounds.contains(marker.position)),
);
}
});
allRenderedMarkers.addAll(visibleMarkers);
return visibleMarkers;
}
void exec() {
final bounds = LatLngBounds(LatLng(10, 10), LatLng(20, 20));
final markers = List.generate(
400000, (i) => Marker(LatLng(10 + i % 10, 10 + i % 10))).toSet();
final markerSources = {
MarkerType.type1: MarkerSource(markers),
MarkerType.type2: MarkerSource(markers),
MarkerType.type3: MarkerSource(markers),
};
final visibility = {
MarkerType.type1: true,
MarkerType.type2: false,
MarkerType.type3: true,
};
final allRenderedMarkers = <Marker>{};
final stopwatch = Stopwatch()..start();
calculateVisibleMarkers1(
bounds, markerSources, visibility, allRenderedMarkers);
stopwatch.stop();
print('Implementation 1: ${stopwatch.elapsedMilliseconds}ms');
stopwatch.reset();
stopwatch.start();
calculateVisibleMarkers2(
bounds, markerSources, visibility, allRenderedMarkers);
stopwatch.stop();
print('Implementation 2: ${stopwatch.elapsedMilliseconds}ms');
stopwatch.reset();
stopwatch.start();
calculateVisibleMarkers3(
bounds, markerSources, visibility, allRenderedMarkers);
stopwatch.stop();
print('Implementation 3: ${stopwatch.elapsedMilliseconds}ms');
}
void main() {
for (int i = 0; i < 5; ++i) {
print("------------------------------------");
print("Simulation ${i + 1}");
exec();
}
return;
}
@ninjaasmoke
Copy link
Author

------------------------------------
Simulation 1
Implementation 1: 350ms
Implementation 2: 162ms
Implementation 3: 140ms
------------------------------------
Simulation 2
Implementation 1: 480ms
Implementation 2: 140ms
Implementation 3: 138ms
------------------------------------
Simulation 3
Implementation 1: 463ms
Implementation 2: 159ms
Implementation 3: 152ms
------------------------------------
Simulation 4
Implementation 1: 408ms
Implementation 2: 150ms
Implementation 3: 143ms
------------------------------------
Simulation 5
Implementation 1: 381ms
Implementation 2: 147ms
Implementation 3: 137ms

Conclusion:

Implementation 3 consistently outperforms others in terms of time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment