Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upstyle: Add a simple rule-tree benchmarks. #14485
Conversation
|
Looks like there are a few tidy issues. |
|
Fixed, also matched the two workloads so the test is more meaningful, and fixed a race condition in the node-dropping code. |
|
|
|
|
rebased. ping @heycam :) |
|
|
|
@heycam review ping? |
|
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.
This comment has been minimized.
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.
This comment has been minimized.
| // 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.
This comment has been minimized.
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.
This comment has been minimized.
| } | ||
|
|
||
| #[bench] | ||
| fn bench_expensive_insersion(b: &mut Bencher) { |
This comment has been minimized.
This comment has been minimized.
| s.spawn(|s| { | ||
| for _ in 0..1000 { | ||
| test::black_box(test_insertion(&r, | ||
| rules_matched.clone())); |
This comment has been minimized.
This comment has been minimized.
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.
This comment has been minimized.
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.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| (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.
This comment has been minimized.
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.
This comment has been minimized.
heycam
Dec 16, 2016
Member
Can we use a HashSet instead? Otherwise we take quadratic time running these checks.
This comment has been minimized.
This comment has been minimized.
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.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| b.iter(|| { | ||
| test::black_box(test_insertion(&r, rules_matched.clone())); | ||
|
|
||
| unsafe { r.gc() }; |
This comment has been minimized.
This comment has been minimized.
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.
This comment has been minimized.
|
Let me try to elaborate on the drop changes. It's not that we're calling What we did was something like:
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 The way I've solved this is setting the free list pointer to null while we're modifying it. |
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). |
|
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.
This comment has been minimized.
| } | ||
|
|
||
| // Else store the old head as the next pointer, and store ourselves as | ||
| // the old head. |
This comment has been minimized.
This comment has been minimized.
3e97e8f
to
3f5a486
|
@bors-servo r=heycam |
|
|
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 r=heycam
|
|
|
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 retry #12797 |
|
|
|
|
emilio commentedDec 7, 2016
•
edited by larsbergstrom
r? @heycam
Numbers on my machine, for the record:
This change is