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

Add a one-token cache #171

Merged
merged 15 commits into from
Jul 24, 2017
Merged

Add a one-token cache #171

merged 15 commits into from
Jul 24, 2017

Conversation

SimonSapin
Copy link
Member

@SimonSapin SimonSapin commented Jul 18, 2017

This makes the Servo_DeclarationBlock_SetPropertyById micro-benchmark being added in https://bugzilla.mozilla.org/show_bug.cgi?id=1344131 faster by ~10%.


This change is Reviewable

}

impl<'a> From<&'a str> for CompactCowStr<'a> {
#[inline]
fn from(s: &'a str) -> Self {
let len = s.len();
assert!(len <= MAX_LEN);
assert!(len < usize::MAX);
Copy link
Member

Choose a reason for hiding this comment

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

I think this would be (slightly) clearer as != usize::MAX.

fn as_raw_str(&self) -> *const str {
unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(self.ptr, self.len()))
fn unpack(&self) -> Result<&'a str, *const String> {
Copy link
Member

Choose a reason for hiding this comment

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

Could this please have some docs? I found the name not super-descriptive.

src/parser.rs Outdated
// ```
// parser.try(|parser| {
// match parser.next() { … }
// }).or_else(|| {
Copy link
Member

Choose a reason for hiding this comment

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

Won't this change behaviour if I do:

parser.try(|p| match parser.next_including_whitespace_and_comments() { .. })
    .or_else(|| match parser.next_including_whitespace_and_comments() { .. })

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIU, the position won't be the same after the whitespace token and thus the cache won't be used.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, right

@SimonSapin
Copy link
Member Author

SimonSapin commented Jul 18, 2017

SetPropertyById faster by ~10%.

It also makes full stylesheet parsing slower, so let’s not land this just yet :(

@SimonSapin
Copy link
Member Author

SimonSapin commented Jul 21, 2017

Alright, in the current state of this PR (with a bunch of changes to the Servo repository for which I’ll open a PR next), gecko benchmarks changes are:

  • Full stylesheet parsing: unchanged (or within noise level)
  • Parsing (eCSSProperty_width, "10px"): ~15% faster
  • Parsing (eCSSProperty_width, " 10px") (note extra space): ~5% slower

The regression is unfortunate. An additional change (not caching whitespace tokens that are skipped by Parser::next) fixes it (makes the " 10px" bench ~15% faster than master) but also makes full stylesheet parsing ~20% slower, so I removed that change from the PR.

I’ll keep trying other things, but I’d still like to land this so that the Servo changes do not bitrot too much. r? @emilio

bors-servo pushed a commit to servo/servo that referenced this pull request Jul 21, 2017
Update cssparser to 0.18

Do not merge yet, depends on servo/rust-cssparser#171.
bors-servo pushed a commit to servo/servo that referenced this pull request Jul 21, 2017
Update cssparser to 0.18

Do not merge yet, depends on servo/rust-cssparser#171.

<!-- 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/17820)
<!-- Reviewable:end -->
Copy link
Member

@emilio emilio left a comment

Choose a reason for hiding this comment

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

(Just a few comments, will review properly tomorrow)

@@ -245,6 +245,15 @@ impl<'a> Tokenizer<'a> {
}

#[inline]
pub fn see_function(&mut self, name: &str) {
if self.var_functions == SeenStatus::LookingForThem {
Copy link
Member

Choose a reason for hiding this comment

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

nit: I'd probably use early-return here.

Copy link
Member

Choose a reason for hiding this comment

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

and below.

src/color.rs Outdated
@@ -141,7 +141,7 @@ impl Color {
///
/// FIXME(#2) Deprecated CSS2 System Colors are not supported yet.
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Color, BasicParseError<'i>> {
let token = input.next()?;
let token = input.next()?.clone();
Copy link
Member

Choose a reason for hiding this comment

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

is this clone needed? couldn't you just use match *token? I guess maybe you can't parse the nested block below, is that it?

And, you need the clone below for the error?

Copy link
Member Author

Choose a reason for hiding this comment

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

Cloning is needed so that input is not still borrowed by the time we call input.parse_nested_block in the Token::Function case below. This is language limitation, non-lexical lifetimes will hopefully make this clone unnecessary. I’ll add a comment.

You’re right though that this clone makes the other one unnecessary, I’ll remove that.

@@ -475,7 +471,7 @@ fn parse_rgb_components_rgb<'i, 't>(arguments: &mut Parser<'i, 't>) -> Result<(u
}
Token::Percentage { unit_value, .. } => {
red = clamp_unit_f32(unit_value);
green = clamp_unit_f32(match arguments.next()? {
green = clamp_unit_f32(match arguments.next()?.clone() {
Copy link
Member

Choose a reason for hiding this comment

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

Hmm... This is kind of unfortunate, because it means that before we created a token, and now we need to create two copies of it... Does it happen too often? I wonder if that's why parsing a stylesheet becomes slower?

Copy link
Member Author

Choose a reason for hiding this comment

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

Parsing initially became slower when Parser::next would clone every single token in order to put in the cache. Returning &Token removed these clones. In a minority of cases like here, the callers had to do these clones themselves instead. Note though that Token::clone never allocates. (Refcounting is used when a token contains an allocation.)

I don’t know the reason for the more recent regression. I’ll investigate next week.

Copy link
Member

@emilio emilio left a comment

Choose a reason for hiding this comment

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

Looks good, I wonder if we could make a Rc<str> instead of an Rc<String>, which AIUI double-allocates...

@SimonSapin
Copy link
Member Author

rust-lang/rust#42565 adds From<&str> for Rc<str> but has not landed yet. Also, Rc<str> is a fat pointer, which would make this bit packing more tricky. (Rc::<T>::into_raw and Rc::<T>::from_raw are only available for T: Sized.)

@SimonSapin
Copy link
Member Author

Ideally we’d want a growable RcString that contains refcount, length, capacity, and data all in one allocation. I tried it, but the amount of rarely-exercised unsafe code this required didn’t seem worth it.

@emilio
Copy link
Member

emilio commented Jul 23, 2017

Yeah, fair enough... Anyway, feel free to land with r=me when you feel comfortable with it.

@SimonSapin
Copy link
Member Author

Cool, thanks. Maybe servo/servo#17820 should be ready too before we land this one. It has a green servo try run but still need review. Do you want to take it as well? It’s fairly mechanical.

@SimonSapin
Copy link
Member Author

@bors-servo r=emilio

@bors-servo
Copy link
Contributor

📌 Commit 850eac1 has been approved by emilio

@bors-servo
Copy link
Contributor

⌛ Testing commit 850eac1 with merge efcfb37...

bors-servo pushed a commit that referenced this pull request Jul 24, 2017
Add a one-token cache

This makes the `Servo_DeclarationBlock_SetPropertyById` micro-benchmark being added in https://bugzilla.mozilla.org/show_bug.cgi?id=1344131 faster by ~10%.

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

☀️ Test successful - status-travis
Approved by: emilio
Pushing efcfb37 to master...

@bors-servo bors-servo merged commit 850eac1 into master Jul 24, 2017
@SimonSapin SimonSapin deleted the token-cache branch July 24, 2017 09:33
SimonSapin added a commit to servo/servo that referenced this pull request Jul 24, 2017
SimonSapin added a commit to servo/servo that referenced this pull request Jul 24, 2017
bors-servo pushed a commit to servo/servo that referenced this pull request Jul 24, 2017
Update cssparser to 0.18

Do not merge yet, depends on servo/rust-cssparser#171.

<!-- 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/17820)
<!-- Reviewable:end -->
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Jul 25, 2017
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : e4825d4514cfe2286e2f874b4bd643befe603521
JerryShih pushed a commit to JerryShih/gecko-dev that referenced this pull request Jul 27, 2017
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6
aethanyc pushed a commit to aethanyc/gecko-dev that referenced this pull request Jul 28, 2017
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this pull request Oct 1, 2019
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6

UltraBlame original commit: e5aad4922fba8855a4bfc979adf4e56c44d6db8c
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this pull request Oct 1, 2019
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6

UltraBlame original commit: e5aad4922fba8855a4bfc979adf4e56c44d6db8c
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this pull request Oct 1, 2019
…e); r=emilio

Do not merge yet, depends on servo/rust-cssparser#171.

Source-Repo: https://github.com/servo/servo
Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6

UltraBlame original commit: e5aad4922fba8855a4bfc979adf4e56c44d6db8c
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.

4 participants