-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Use murmur hash on symbol instance keys to reduce worker transfer costs. #7127
Conversation
OK,
I did a little bit of profiling, and struct array "get()" calls now show up peppered through all the placement/opacity-update code, but I'm not sure how significant it is. I think it's probably a little bit of a trade-off between CPU time spent in placement and time blocked transferring tile data. Let's just try to figure out some benchmarks that can give us a good idea of which is better? |
🤷♂️ Maybe this is a decent win? I think my machine is just lagging overall today for me so it felt pretty stuttery but when I did 40 seconds of animation going back and forth between zooms 7 and 16 in DC, I got 53.1 FPS before the change and 56.5 FPS after. |
After restarting my computer, I started getting results closer to what I'm used to, and it looks promising: as if we're roughly back to v0.45 performance after all the changes. Each cell is number of frames generated over 10 second zoom animation, 600=60 FPS. The first entry in the table is slower because no tiles are cached (think of the first line in the table as the one that really exercises the worker transfer changes). 1071x854px viewport on 2016 MBP, location of
Murmur hash only added ~1.5KB to the bundle, but it looks like all the new struct array stuff added another ~5K. 😞 |
@@ -941,6 +1005,96 @@ export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub40 { | |||
|
|||
register('PlacedSymbolArray', PlacedSymbolArray); | |||
|
|||
class SymbolInstanceStruct extends Struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
running yarn run codegen
gets rid of this. Do you have some uncommitted changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😳 OMG you mean I didn't have to make that all by hand. 🤦♂️
36d723c
to
15fffa9
Compare
I modified the code-gen to add an optional "non-transferable members" argument to |
Preparation for making symbolInstances array transferrable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the end for this PR I'm just adding crossTileID, and it'd probably work just as well to explicitly generate that in the background as "0" and transfer it...
Do you foresee other things using this? If not, do you think it's worth removing this and just generating it in the background?
src/data/bucket/symbol_bucket.js
Outdated
@@ -538,15 +518,26 @@ class SymbolBucket implements Bucket { | |||
arrays.programConfigurations.populatePaintArrays(arrays.layoutVertexArray.length, feature, feature.index); | |||
} | |||
|
|||
_addCollisionDebugVertex(layoutVertexArray: StructArray, collisionVertexArray: StructArray, point: Point, anchor: Point, extrude: Point) { | |||
addSymbolInstance(anchorX: number, anchorY: number, horizontalPlacedTextSymbolIndex: number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to just call symbolInstances.emplaceBack(...)
directly instead of through this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup.
This change decreases worker transfer time which should decrease jankiness during tile loading. However, there is some extra overhead in accessing the StructArray of symbolInstances during render-time symbol placement. If we identify hotspots, the most direct optimization is to used indexed accessors into the underlying TypedArray, instead of using the `get(i).property` approach.
15fffa9
to
0fd76c1
Compare
When I started on the changes, there were more things that needed it, but in the end it was really just |
src/data/bucket/symbol_bucket.js
Outdated
const aRotated = Math.round(sin * a.anchor.x + cos * a.anchor.y) | 0; | ||
const bRotated = Math.round(sin * b.anchor.x + cos * b.anchor.y) | 0; | ||
const a = this.symbolInstances.get(aIndex); | ||
const b = this.symbolInstances.get(bIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make sure sorting doesn't get more expensive here — perhaps worth trying to build rotated
and featureIndices
arrays first and then only do (rotated[aIndex] - rotated[bIndex]) || (featureIndices[bIndex] - featureIndices[aIndex])
in the comparison function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I'll do that. 👍
Start using murmurhash-js on symbol instance "keys" for use in the cross tile symbol index. This may theoretically reduce memory consumption a little bit -- but the main goal is to be able to convert the
symbolInstances
array into a transferrable type to reduce worker transfer costs.Loading some z14 LA streets, I don't see much of a difference -- I think this is because the hashed key ends up getting converted to a string that's not that different from the average length of a road name, e.g. "1239807915" vs. "Maple Ave.". So this change doesn't really buy us anything until we finish converting symbolInstances into a transferrable type.
write tests for all new functionalitydocument any changes to public APIstagged@mapbox/studio
and/or@mapbox/maps-design
if this PR includes style spec changescc @mourner @ansis