Anyone else tried out the new MKPointAnnotation clustering feature?
I have serious performance issues on the map after adding 900 (or less) annotations to mapkit on low zoom levels. (zooming, panning etc.)
The annotations are getting clustered correctly on each region change event but the map is laggy and unresponsive.
I have a set of "stops" (public means of transport) that is loaded on higher zoom values (zoom in).
On lower zoom values (zoom out), I am using "departures" (about 3x the count of the visible "stops").
I did the clustering manually before and there was no lag at all.
The documentation and WWDC 2017 videos do not mention anything about performance or best practice for efficient clustering.
In general, I only add annotations that can be visible in the current mapRect (of course, when zooming out they become more an moreā¦)
I've also tried out the MapKit demo app "Tandm" with about 900 annotations and it had similar performance issues.
I also ran the profiler and the performance issues seem to be caused by the internal MKAnnotation renderer when it updates the visible annotations.
I think the main issue is, that there are simply too many visible clusters. I haven't found a way to change that behavior to fit my needs.
I have tried setting the clusterIdentifier to different values and ended up setting it always to "stops" works "best".
Of course I could limit the data when zooming out but I think the clustering should be able to handle that.
Here is a video: https://www.dropbox.com/s/8bubd9ib76pmz47/mapkit-lag.mov?dl=0
The function visibleAnnotations() takes about 30% of the execution time 70% are taken by MapKit when updating the annotations.
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if #available(iOS 11.0, *) {
if let visibleAnnotations = visibleAnnotations() {
let oldAnnotations = mapView.annotations
mapView.removeAnnotations(oldAnnotations)
mapView.addAnnotations(visibleAnnotations)
}
}
}
Related
I have a custom ListCell implementation, shown in the picture below.
The left side, which represents the date, consisting of 3 labels, put in a VBox and the "CounterContent" consisting of the counter, with a TextField for each digit, contained in a HBox, and two Hboxes containing labels for kWh, kWh/day and so on. And that seem to be just too much, to be running performantly.
I've tried to load the data in a background task, showing a progress indicator, while the task is running, but unlike on desktop, on android the performance is very poor. Whenever I switch to the listview, the garbage collection kicks in, and blocks the ui thread, so that the progress indicator never shows up.
I've tried it on a Huawei Y-300, Android 4.1.1, javafxports 8.60.6 (because javafxports 8.60.7 causes a bug, that makes TextField unusable), and on a Samsung S5 mini, Android 5+. On the Samsung phone the performance in general is way better, just like expected, because of the Ahead-of-Time compilation I guess, but there is still the garbage collection issue. Furthermore after the listview has been populated with cells, the scrolling is not very smooth.
Is the listcell to complex or what else could be the matter for the poor performance?
UPDATE:
After running a lot of tests it seems the unsmooth scrolling is not caused by performance problems. At least on the S5 (javafxports 8.60.7).
I removed all css styling, and replaced the textfields by a single label (the counter node is already a custom control(forgot about that), which lays out the textfields in 2 Regions(not HBoxes) and the nodes of the ListCell are instantiated in the constructor). Furthermore I switched the ListView for a CharmListView and set android.monocle.input.touchRadius=1.
None of these steps resulted in considerable improvement.
Just to clarify: In contrast to the Huawei phone, the scrolling on the S5 and android 5+ is usable, but it's not very smooth, which makes for a unsatisfactory user experience.
On the Huawei (javafxports 8.60.6), changing the counter textfields for a label, gave a significant improvement, but not to the point where the scrolling became usable. Until I set this magical experimental switch: gluon.experimental.performance=true, which makes the listview scrolling lightning fast(after a little warmup delay), but still not really smooth.
There are many reasons why the performance of a complex scene is reduced, so this is just a list of possible ideas that might help improving it, in any order.
ListCell
For starters, the number of nodes in the cell is really high. Notice that every single scroll you make means the full rendering of the virtual flow that holds the visible cells. And for every cell, that means recreating its content all over again.
Without viewing your code I can't tell, but you should avoid creating new instances of every node in the cell all the time, by having just one single instance, and in the updateItem method only change the content of the nodes.
Have a look at this sample. The NoteCell class is a custom cell, where a ListTile is used.
Number of nodes
Have you tried using just a Label to replace the 8 textfields and 3 boxes?
Cache
If you use images downloaded from Internet, use Gluon Charm Down Cache to avoid the same image being downloaded over and over again.
Have a look at this sample. Without the cache, even on desktop the performance is really affected.
Also use the JavaFX built-in cache for any node, trying different cache strategies.
CSS
Complex CSS requires long CPU time. Try to simplify it. Even you can remove the whole CSS for a quick test. Then decide what you may or may not use.
The same goes for animations: Avoid animations, transitions or even CSS effects, if possible.
Custom Control
The counter complex node could probably be replaced by a custom control that optimizes the rendering.
CharmListView
Have you tried using the Gluon Charm CharmListView control instead of the ListView?
There's a new experimental flag that you can use to test a possible optimization that might improve performance while scrolling the list. Set gluon.experimental.performance=true on the java.custom.properties file, and give it a try.
JavaFXPorts version
You mentioned you are using 8.60.6 because of the TextField bug. In this case, are your TextField nodes editable? If not, I'd suggest replacing them with other nodes and running with 8.60.7, since it contains a lot of performance improvements.
Performance tools
Use performance tools like Monitor and use its profiling options so you can trace down any possible bottle neck.
CPU
Last but not least: your mobile device specs are always critical.
Trying to render a complex scene on a Cortex A5, given that "it is the smallest, lowest cost and lowest power ARMv7 application processor", or using a very old Android 4.1.1, can't perform as well as running it on a brand new device with higher specs.
As you also mentioned, running on a Cortex A7 performs "way better". Have a look at this comparison, and find the right architecture for the job.
Anyway, there's always room for improvement, and a lot of effort is put into it. Your feedback is always welcome.
I have run into some pretty bad UX problems while developing with angular google maps and am looking for advice on the best way to proceed.
Relevant template:
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" bounds="map.bounds">
<ui-gmap-markers doCluster="true" models="randomMarkers" coords="'self'" icon="'icon'">
</ui-gmap-markers>
</ui-gmap-google-map>
Plunkr: http://plnkr.co/edit/mZvN6wCT9LCl1DWGojZD?p=preview
Two problems, both related to clustering:
First, on any sort of map event, most annoyingly drag, the clusters blink as they repaint, even if the cluster did not change position.
Second, the clusters disappear when they fall off the visible section of the map, which is probably good for performance but more of a UI pain if you're dealing with maps at a high zoom level, where things are in and out of the map's view all the time.
These issues are not apparent at the markercluster demo page:
http://gmaps-utility-library-dev.googlecode.com/svn/tags/markerclusterer/1.0/examples/advanced_example.html
How have you addressed these issues? I've looked through the API's for both angular google maps and markerclustererplus, but to no avail.
I was under the assumption that the clusterer would just figure out which points belonged together, then make a marker that symbolized that collection. However it seems that the clusters behave so differently than markers (eg. the above issues) that this can't be the case.
I am trying to create an application with an OpenGL view using MonoMac. Setting up an application and an NSOpenGLView was fairly simple...
...but for some reason I cannot get a consistent frame rate rendering OpenGL. The issue I am having is that 9 out of ten frames have perfect performance and every tenth frame or so I am getting a massive frame time spike (about 60ms-80ms for a single frame). The time of the slow frame correlates with the size of the control (and even more so using retina backing buffer).
I have been digging and have come up with nothing that works for my case.
I tried to use NSOpenGLView with CVDisplayLink and rendering on the main thread with timers and DrawRect.
I tried MonoMacGameView also both versions. Actually MonoMacGameView has consistent performance but only draws when my window does not have a background color.
I reimplemented the run loop to do my own NextEvent polling just to find out that that is not the issue...
So, my current hunch is that it has something to do with layer backed rendering in Cocoa views but I really cannot figure out what is causing this.
Any hint as to what is causing this delay?
I found a solution which produces pretty good results:
Do not use NSOpenGLView or MonoMacGameView.
Use the approach described in the example on this page: http://cocoa-mono.org/archives/366/monomac-and-opengl/
To enable retina support export the ContentScale property on the deriving class and set that depending whether you are running on retina screen or not
In conclusion, using a core animation layer is the only viable solution.
I'm working on a Cocoa application which will be used for a digital-signage/kiosk style display. I've never done anything like this with Cocoa before, but I'm trying to figure out what the best approach is for building the user interface for it.
My main issue is that I need a way to have the user interface scaled up or down depending on the resolution of the display. When I say scaled, I mean that I want everything including white space to maintain the same sizing ratio. The aspect ratio of the interface needs to remain the same (16x9), but it should always fill the entire width of the display its on.
Sorry if I'm not being descriptive enough.
What are some thoughts?
If I follow you correctly, you want all buttons and views, etc. to get larger, the bigger the screen is (which has nothing to do with the dimensions of your views). If that's the case, there's no automatic way to do this.
With Quartz Debugger (part of Xcode Tools), you can set the scaling factor (see "resolution independence"), but this would need to be manually adjusted per system. What's more is I'm not sure if this tinge is persistent across reboots. I leave that for you to investigate.
As far as I know, though, there's no way to adjust this programmatically as resolution independence is still not an exposed consumer feature of OS X.
If anyone is interested, I seem to have found a solution under this post: http://cocoawithlove.com/2009/02/asteroids-style-game-in-coreanimation.html
I'm writing a video annotation application with Qt4 in which users need to be able to seek to various points in a video, putting markers on various objects and then setting keypoints for those markers so that they stay on the objects in the video as they move around. QGraphicsItemAnimation seems like a great place to start for these markers, however they need to be able to appear and disappear at specific times, which I can't figure out how to do with the QGraphicsItemAnimation. I could set the scale at 0 to make the objects disappear, but that seems like a pretty hacky solution, and I'm guessing that the paint engine would still waste cpu cycles trying to draw those invisible objects. Does anyone have a better solution than this? I'm using Qt 4.5.3 right now, but I'm willing to upgrade to 4.6 if it makes things easier. Thanks!!
It seems like the functionality you want of showing/hiding QGraphicsItem objects is beyond the scope of the simple "tweening" that the animation class performs. It is only for one object at a time, and any appearance or disappearance you have to write yourself.
You still might get some mileage out of QGraphicsItemAnimation (although the fact that it uses its own timer instead of being locked to the frame clock of your video is a little dodgy).
Neglecting "seeking" for a moment, there is a QTimeLine::finished() signal. If you let the end of an annotation's active animation timeline represent the point where you want it to disappear, you can trigger QGraphicsItem::hide() at that point. When it comes time to turn it back on, you would construct a new QGraphicsItemAnimation (based on the next run of keyframe data for that object) and call QGraphicsItem::show().
Note that one of the headlining features of Qt 4.6 is the QtAnimation framework, which is more sophisticated but also rather complex. I've not used it yet, but looking over the examples it seems like you might be able to "animate" a visibility or opacity property.