Skip to content
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

Simplify the ClipId -> CST id mapping code. #2925

Merged
merged 4 commits into from Jul 24, 2018
Merged

Conversation

gw3583
Copy link
Contributor

@gw3583 gw3583 commented Jul 23, 2018

There are some upcoming changes which will modify how and when
we store and represent clip nodes and chains. These changes are
necessary to allow WR to rasterize pictures in a different coordinate
space than just screen space.

This patch simplifies the mapping of ClipId to array indices in
the clip-scroll tree. This will make it simpler to make the
changes discussed above - specifically, we can unify how we handle
clip nodes with the per-primitive complex clips.

The code this removes was a performance optimization to avoid
hashmap lookups. I did some profiling on a number of real world
sites and also on some gecko layer stress tests, and didn't find
any noticeable regression from simplifying this code. However,
once the work above has been completed, we could re-investigate
how to optimize this mapping process, if it ever shows up in a
profile.

In one of the stress tests [1] for spatial and clip node creation,
the code is now slightly faster with this patch (28ms vs 29ms).

[1] https://mattwoodrow.github.io/dl-test/dl-test.html?count=50000&layer=inactive


This change is Reviewable

@gw3583
Copy link
Contributor Author

gw3583 commented Jul 23, 2018

@gw3583
Copy link
Contributor Author

gw3583 commented Jul 23, 2018

Gecko try looks good.

@gw3583
Copy link
Contributor Author

gw3583 commented Jul 23, 2018

@gw3583
Copy link
Contributor Author

gw3583 commented Jul 23, 2018

Try still looks good 👍

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but needs @mrobinson to review as well if they are available

@@ -1772,16 +1772,16 @@ impl ClipBatcher {
) {
let mut coordinate_system_id = coordinate_system_id;
for work_item in clips.iter() {
let info = clip_store
.get_opt(&work_item.clip_sources)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why get_opt if we follow with expect right away?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because (for now) we only have a weak handle here, so the freelist API doesn't guarantee it's present, but we know that it should be due to usage here. I intend to refactor how we store clip sources as part of this work.

}

impl ClipSources {
pub fn new(clips: Vec<ClipSource>) -> Self {
pub fn new(
clips: Vec<ClipSource>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could use Iterator<Item = ClipSource> to avoid heap allocation on the client

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me how this avoids an allocation in this case - could you expand on that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't need a vec, since it goes through the elements and constructs other stuff from them. But it's currently requiring the caller to have that vec. If this function gets IntoIterator instead, the caller may still provide a vec, or they can just construct a complex iterator (with chain(), zip(), etc) that is completely on the stack. IIRC, there is at least one place in code where this would be handy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're right - I misread that it took ownership of it, missing the collect. Although, having tried to make that change it seems to flow on to changing several other functions, so perhaps better to leave for now (since this PR doesn't actually change that code), unless I'm missing an obvious way to make this change locally?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be correct to change the calling functions as well, where possible, but at the same time Vec implements IntoIterator so those changes are not required. I'll be happy to follow up with this refactor ;)

self.cached_clip_chain_index = Some((*id, index));
index
pub fn map_spatial_node(&mut self, id: ClipId, index: SpatialNodeIndex) {
debug_assert!(!self.spatial_node_map.contains_key(&id));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could use the returned value from insert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -34,6 +34,29 @@ pub struct HitTestClipNode {
regions: Vec<HitTestRegion>,
}

impl HitTestClipNode {
fn new(node: &ClipNode, clip_store: &ClipStore) -> HitTestClipNode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: -> Self

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

There are some upcoming changes which will modify how and when
we store and represent clip nodes and chains. These changes are
necessary to allow WR to rasterize pictures in a different coordinate
space than just screen space.

This patch simplifies the mapping of ClipId to array indices in
the clip-scroll tree. This will make it simpler to make the
changes discussed above - specifically, we can unify how we handle
clip nodes with the per-primitive complex clips.

The code this removes was a performance optimization to avoid
hashmap lookups. I did some profiling on a number of real world
sites and also on some gecko layer stress tests, and didn't find
any noticeable regression from simplifying this code. However,
once the work above has been completed, we could re-investigate
how to optimize this mapping process, if it ever shows up in a
profile.

In one of the stress tests [1] for spatial and clip node creation,
the code is now slightly faster with this patch (28ms vs 29ms).

[1] https://mattwoodrow.github.io/dl-test/dl-test.html?count=50000&layer=inactive
@@ -56,8 +56,8 @@ pub struct ClipIdToIndexMapper {

impl ClipIdToIndexMapper {
pub fn add_clip_chain(&mut self, id: ClipId, index: ClipChainIndex) {
debug_assert!(!self.clip_chain_map.contains_key(&id));
self.clip_chain_map.insert(id, index);
let _is_new_key = self.clip_chain_map.insert(id, index).is_none();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's not confuse the reader with is_none() here and instead move it inside the assert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@mrobinson
Copy link
Member

If the LRU cache and non-hashing mapping aren't important to the code, then these changes simplify the code a lot. Looks good to me.

@gw3583
Copy link
Contributor Author

gw3583 commented Jul 24, 2018

@mrobinson Thanks for taking a look! I think it's possible we will want the non-hashing optimization back in the future (especially for stress tests), but it doesn't seem to be providing a huge win right now (I wonder if we're either hashing less than we used to, or perhaps it's not such an issue now that we are using the Fx hasher instead of Fnv?).

@mrobinson
Copy link
Member

mrobinson commented Jul 24, 2018

@glennw It's an interesting question. It could be that this approach is still hashing quite a bit less than when we were not storing ClipScrollTree nodes in vectors and converting the ids to indexes.

@kvark
Copy link
Member

kvark commented Jul 24, 2018

@bors-servo r=kvark,mrobinson

@bors-servo
Copy link
Contributor

📌 Commit 66ad1c4 has been approved by kvark,mrobinson

@bors-servo
Copy link
Contributor

⌛ Testing commit 66ad1c4 with merge 3779039...

bors-servo pushed a commit that referenced this pull request Jul 24, 2018
Simplify the ClipId -> CST id mapping code.

There are some upcoming changes which will modify how and when
we store and represent clip nodes and chains. These changes are
necessary to allow WR to rasterize pictures in a different coordinate
space than just screen space.

This patch simplifies the mapping of ClipId to array indices in
the clip-scroll tree. This will make it simpler to make the
changes discussed above - specifically, we can unify how we handle
clip nodes with the per-primitive complex clips.

The code this removes was a performance optimization to avoid
hashmap lookups. I did some profiling on a number of real world
sites and also on some gecko layer stress tests, and didn't find
any noticeable regression from simplifying this code. However,
once the work above has been completed, we could re-investigate
how to optimize this mapping process, if it ever shows up in a
profile.

In one of the stress tests [1] for spatial and clip node creation,
the code is now slightly faster with this patch (28ms vs 29ms).

[1] https://mattwoodrow.github.io/dl-test/dl-test.html?count=50000&layer=inactive

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2925)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

☀️ Test successful - status-appveyor, status-taskcluster
Approved by: kvark,mrobinson
Pushing 3779039 to master...

@bors-servo bors-servo merged commit 66ad1c4 into servo:master Jul 24, 2018
bors-servo pushed a commit that referenced this pull request Aug 1, 2018
Replace heap allocation of clip-related objects with iteration

This PR makes scene building faster by doing less heap allocations.

r? @gankro or @gw3583
cc @gw3583  - this is a follow-up to #2925 that I figured I'd forget about if I don't do it now ;)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2943)
<!-- Reviewable:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants