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

style: Add a simple rule-tree benchmarks. #14485

Merged
merged 2 commits into from Dec 19, 2016
Merged

style: Add a simple rule-tree benchmarks. #14485

merged 2 commits into from Dec 19, 2016

Conversation

@emilio
Copy link
Member

emilio commented Dec 7, 2016

r? @heycam

Numbers on my machine, for the record:

test rule_tree::bench::bench_expensive_insersion          ... bench:   7,211,081 ns/iter (+/- 1,933,866)
test rule_tree::bench::bench_expensive_insersion_parallel ... bench:  78,728,097 ns/iter (+/- 11,738,010)
test rule_tree::bench::bench_insertion_basic              ... bench:     665,333 ns/iter (+/- 68,089)
test rule_tree::bench::bench_insertion_basic_parallel     ... bench:   1,587,203 ns/iter (+/- 372,124)

This change is Reviewable

@frewsxcv
Copy link
Member

frewsxcv commented Dec 8, 2016

Looks like there are a few tidy issues.

@emilio emilio force-pushed the rule-tree-bench branch from 296e07a to a49c6a1 Dec 8, 2016
@emilio
Copy link
Member Author

emilio commented Dec 8, 2016

Fixed, also matched the two workloads so the test is more meaningful, and fixed a race condition in the node-dropping code.

@emilio
Copy link
Member Author

emilio commented Dec 8, 2016

test rule_tree::bench::bench_expensive_insersion          ... bench: 125,770,757 ns/iter (+/- 4,556,363)
test rule_tree::bench::bench_expensive_insersion_parallel ... bench:  76,942,732 ns/iter (+/- 12,462,937)
test rule_tree::bench::bench_insertion_basic              ... bench:   1,581,405 ns/iter (+/- 92,483)
test rule_tree::bench::bench_insertion_basic_parallel     ... bench:     938,729 ns/iter (+/- 62,497)
test rule_tree::bench::bench_insertion_basic_per_element  ... bench:         359 ns/iter (+/- 22)
@emilio emilio removed the S-fails-tidy label Dec 8, 2016
@bors-servo
Copy link
Contributor

bors-servo commented Dec 10, 2016

The latest upstream changes (presumably #14535) made this pull request unmergeable. Please resolve the merge conflicts.

@emilio emilio force-pushed the rule-tree-bench branch from a49c6a1 to 37ec4d8 Dec 10, 2016
@emilio
Copy link
Member Author

emilio commented Dec 10, 2016

rebased. ping @heycam :)

@bors-servo
Copy link
Contributor

bors-servo commented Dec 15, 2016

The latest upstream changes (presumably #14592) made this pull request unmergeable. Please resolve the merge conflicts.

@emilio emilio force-pushed the rule-tree-bench branch from 37ec4d8 to 0fca512 Dec 15, 2016
@emilio
Copy link
Member Author

emilio commented Dec 15, 2016

@heycam review ping?

Copy link
Member

heycam left a comment

I don't really understand why we need these changes to pop_from_free_list. Is it that we are indeed calling this from multiple threads at once, when we shouldn't be?

Can you also explain those changes to me as if I were a person who didn't understand the old code? :-)

Can we add some some more explicit assertions / debug-only locks that prevent us from calling into pop_from_free_list simultaneously? I guess from your comments that storing null in the free list head is a way to do this, but it would be nice if we could have something more obvious/explicit.

Also it would have been good to split out any substantive rule tree changes here from commits that add/change benchmarking.

let r = RuleTree::new();

b.iter(|| {
let rules_matched = parse_rules(

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Do we want this outside of the |iter| call? Although it might be small compared to the 1000 test_insertion calls, I think we want to limit the measurement to the insertion, not parsing.

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

yup, that's right.

// This test case tests a case where you style a bunch of siblings
// matching the same rules, with a different style attribute each
// one.
let rules_matched = parse_rules(

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Same here (and in the other functions). (I guess technically we would want the 1000 style attribute rule creations to happen outside of iter too, but that looks cheaper than the CSS parsing.)

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

Yup.

}

#[bench]
fn bench_expensive_insersion(b: &mut Bencher) {

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

insertion

s.spawn(|s| {
for _ in 0..1000 {
test::black_box(test_insertion(&r,
rules_matched.clone()));

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Can we make test_insertion take the Vec of rules by reference? Then we can avoid measuring the cost of cloning the Vec.

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

Sort of, we need to clone for the style attribute, so seemed a bit more fair this way.

}

#[bench]
fn bench_expensive_insersion_parallel(b: &mut Bencher) {

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

insertion

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

whoops :)

(thread_state::get().is_layout() ||
thread_state::get().is_script()));
let current = me.next_free.load(Ordering::SeqCst);
if !cfg!(feature = "testing") {

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Maybe just move the cfg!() expression into the debug_assert!() expression?

assert!(me.is_root());

let mut current = self.ptr;
let mut seen = vec![];

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Can we use a HashSet instead? Otherwise we take quadratic time running these checks.

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

They're debug-only, so I didn't thought too much about it, but yeah, that's fine.

@@ -73,13 +73,29 @@ fn bench_insertion_basic(b: &mut Bencher) {
.bar { height: 500px; } \
.baz { display: block; }");

for _ in 0..1000 {
for _ in 0..(4000 + 400) {

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Does 4000 + 400 have some significance?

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

The same workload as the others.

b.iter(|| {
test::black_box(test_insertion(&r, rules_matched.clone()));

unsafe { r.gc() };

This comment has been minimized.

@heycam

heycam Dec 16, 2016

Member

Might be worth wrapping the RuleTree object into a struct so that you can call its gc() in a Drop impl, to save repeating this in each test.

This comment has been minimized.

@emilio

emilio Dec 16, 2016

Author Member

Fine for me.

@emilio
Copy link
Member Author

emilio commented Dec 16, 2016

Let me try to elaborate on the drop changes.

It's not that we're calling pop_from_free_list from multiple threads, it's that we're dropping the same node twice from multiple threads. Most of the debug checks are during GC because I wrote them when I was investigating.

What we did was something like:

  1. check the free list pointer. return if we were already in the free list.
  2. Try to insert us in the free list.

But of course, something that doesn't happen while styling but happens during these benchmarks, is that that same node can be inserted in the free list between 1 and 2 (if it's "resurrected" and then dropped again).

The way I've solved this is setting the free list pointer to null while we're modifying it.

@emilio emilio force-pushed the rule-tree-bench branch from 0fca512 to 8c3c7b8 Dec 16, 2016
@heycam
Copy link
Member

heycam commented Dec 19, 2016

But of course, something that doesn't happen while styling but happens during these benchmarks, is that that same node can be inserted in the free list between 1 and 2 (if it's "resurrected" and then dropped again).

Ah, and the reason this can't happen during styling is that we'll never restyle the same element twice (which would otherwise possibly result in releasing then resurrecting a rule node).

@heycam
heycam approved these changes Dec 19, 2016
Copy link
Member

heycam left a comment

r=me with the comments addressed as you see fit.

}
}

// If we've raced with the same node resurrected and dropped it, we're
// done, just store the stuff again and.

This comment has been minimized.

@heycam

heycam Dec 19, 2016

Member

and...? :)

}

// Else store the old head as the next pointer, and store ourselves as
// the old head.

This comment has been minimized.

@heycam

heycam Dec 19, 2016

Member

as the new head?

@emilio emilio force-pushed the rule-tree-bench branch 2 times, most recently from 3e97e8f to 3f5a486 Dec 19, 2016
@emilio
Copy link
Member Author

emilio commented Dec 19, 2016

@bors-servo r=heycam

@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

📌 Commit 3f5a486 has been approved by heycam

@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

Testing commit 3f5a486 with merge bc9ebd8...

bors-servo added a commit that referenced this pull request Dec 19, 2016
style: Add a simple rule-tree benchmarks.

<!-- Please describe your changes on the following line: -->

r? @heycam

Numbers on my machine, for the record:

```
test rule_tree::bench::bench_expensive_insersion          ... bench:   7,211,081 ns/iter (+/- 1,933,866)
test rule_tree::bench::bench_expensive_insersion_parallel ... bench:  78,728,097 ns/iter (+/- 11,738,010)
test rule_tree::bench::bench_insertion_basic              ... bench:     665,333 ns/iter (+/- 68,089)
test rule_tree::bench::bench_insertion_basic_parallel     ... bench:   1,587,203 ns/iter (+/- 372,124)
```

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

bors-servo commented Dec 19, 2016

💔 Test failed - linux-dev

emilio added 2 commits Dec 7, 2016
@emilio emilio force-pushed the rule-tree-bench branch from 388ad3c to fc6bed2 Dec 19, 2016
@emilio
Copy link
Member Author

emilio commented Dec 19, 2016

@bors-servo r=heycam

  • My import PR broke this one, heh.
@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

📌 Commit fc6bed2 has been approved by heycam

@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

Testing commit fc6bed2 with merge cb6a870...

bors-servo added a commit that referenced this pull request Dec 19, 2016
style: Add a simple rule-tree benchmarks.

<!-- Please describe your changes on the following line: -->

r? @heycam

Numbers on my machine, for the record:

```
test rule_tree::bench::bench_expensive_insersion          ... bench:   7,211,081 ns/iter (+/- 1,933,866)
test rule_tree::bench::bench_expensive_insersion_parallel ... bench:  78,728,097 ns/iter (+/- 11,738,010)
test rule_tree::bench::bench_insertion_basic              ... bench:     665,333 ns/iter (+/- 68,089)
test rule_tree::bench::bench_insertion_basic_parallel     ... bench:   1,587,203 ns/iter (+/- 372,124)
```

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

bors-servo commented Dec 19, 2016

💔 Test failed - mac-rel-wpt1

@emilio
Copy link
Member Author

emilio commented Dec 19, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

Previous build results for android, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css, windows-dev are reusable. Rebuilding only arm32, mac-rel-wpt1, mac-rel-wpt2...

@bors-servo
Copy link
Contributor

bors-servo commented Dec 19, 2016

@bors-servo bors-servo merged commit fc6bed2 into master Dec 19, 2016
4 checks passed
4 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
dependency-ci Dependencies checked
Details
homu Test successful
Details
@SimonSapin SimonSapin deleted the rule-tree-bench branch Dec 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
You can’t perform that action at this time.