-
Notifications
You must be signed in to change notification settings - Fork 130
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
Conversation
This make the Clone impl never allocate.
This will avoid duplicating tokenization work, hopefully in most uses of `Parser::try`.
src/compact_cow_str.rs
Outdated
} | ||
|
||
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); |
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.
I think this would be (slightly) clearer as != usize::MAX
.
src/compact_cow_str.rs
Outdated
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> { |
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.
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(|| { |
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.
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() { .. })
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.
AFAIU, the position won't be the same after the whitespace token and thus the cache won't be used.
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.
Oh, right
It also makes full stylesheet parsing slower, so let’s not land this just yet :( |
It’s pretty much useless now that the refcount is almost never one.
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:
The regression is unfortunate. An additional change (not caching whitespace tokens that are skipped by 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 |
Update cssparser to 0.18 Do not merge yet, depends on servo/rust-cssparser#171.
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 -->
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.
(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 { |
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.
nit: I'd probably use early-return here.
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.
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(); |
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.
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?
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.
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() { |
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.
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?
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.
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.
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.
Looks good, I wonder if we could make a Rc<str>
instead of an Rc<String>
, which AIUI double-allocates...
rust-lang/rust#42565 adds |
Ideally we’d want a growable |
Yeah, fair enough... Anyway, feel free to land with r=me when you feel comfortable with it. |
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. |
@bors-servo r=emilio |
📌 Commit 850eac1 has been approved by |
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 -->
☀️ Test successful - status-travis |
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 -->
…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
…e); r=emilio Do not merge yet, depends on servo/rust-cssparser#171. Source-Repo: https://github.com/servo/servo Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6
…e); r=emilio Do not merge yet, depends on servo/rust-cssparser#171. Source-Repo: https://github.com/servo/servo Source-Revision: 4f0821192c112943bb53b4fb04303c1afdde06e6
…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
…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
…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
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