Repository navigation
Build no marker icons before the MarkerListIdentity gate on MapKit - #16
Merged
Merged
Conversation
MapKitMapView.Coordinator.updateContent rebuilt two dictionaries over every marker on each call, before syncMarkers reached its MarkerListIdentity gate: one with each marker's state, and one with each marker's BitmapIcon, which read the @published icon and, for markers with no icon, made a fresh DefaultMarkerIcon() and drew it again. SwiftUI calls updateContent on every body evaluation, camera moves included, so a resent identical list paid for all of it although the gate then threw the work away. Cost of one updateContent with the same content, 144,183 markers, simulator, best of 15: Debug Release 1 in 4 with no icon 2970 ms -> 12.6 ms 2608 ms -> 0.04 ms every marker an icon 111 ms -> 27.0 ms 61 ms -> 0.14 ms Neither dictionary is needed. The state cache duplicated what MapKitMarkerController already keeps from its last processed list (markerStatesById, filled synchronously when the gate lets a list through, before add() runs), now exposed as syncedMarkerState(for:). The icon cache is replaced by reading the icon off the state in mapView(_:viewFor:); toBitmapIcon() keeps the drawn image per icon, and the no-icon marker shares one default image. Reading the current state also means an annotation view recreated after an in-place icon change shows the new icon, rather than whatever the cache held at the last body evaluation. The other iOS providers already put the gate first. Checked on the iPad (Debug): the marker basic and street tree pages look the same as before, and on a check page a new marker state under the same id and an in-place icon change both show up as before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
なぜ
MapKitMapView.Coordinator.updateContentは、syncMarkersの門番(MarkerListIdentity)に届く前に、毎回全マーカーぶんの辞書を 2 つ作っていました。BitmapIconの辞書。@Publishedの icon を読み、アイコンの無いマーカーには毎回DefaultMarkerIcon()を新しく作って描いていました。SwiftUI は body を評価するたび(カメラの移動中も)
updateContentを呼ぶので、同じ一覧を送り直しただけでもこの全部を払い、その後で門番が捨てていました。同じ content で
updateContentを 1 回呼ぶコスト(144,183 本、シミュレータ、15 回の最良値、body 評価 1 回ぶん):何を変えたか
辞書はどちらも要りませんでした。
MapKitMarkerControllerが直近に処理した一覧から持っているもの(markerStatesById、門番を通ったときにadd()より前に同期的に埋まる)の重複でした。これをsyncedMarkerState(for:)として出し、そちらを引きます。mapView(_:viewFor:)で state からアイコンを読みます。toBitmapIcon()はアイコンごとに描いた画像を持っていて、アイコン無しのマーカーは既定の画像 1 枚を使い回します。他の iOS 8 プロバイダはすでに門番が先にあります。
検証
確認できていないもの