-
Notifications
You must be signed in to change notification settings - Fork 61
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
Boxed tokens #34
Boxed tokens #34
Conversation
Oh and by the way: I ran |
@@ -97,6 +96,7 @@ impl SyntaxText { | |||
|
|||
pub fn for_each_chunk<F: FnMut(&str)>(&self, mut f: F) { | |||
enum Void {} | |||
#[allow(clippy::unit_arg)] |
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 personally don't like clippy-related attributes in the source. Could it be removed?
Moreover, in this case, this is clearly a false-positive, as ()
is spelled explicitly :)
@@ -191,7 +191,6 @@ fn zip_texts<I: Iterator<Item = (SyntaxToken, TextRange)>>(xs: &mut I, ys: &mut | |||
x.1 = TextRange::from_to(x.1.start(), x.1.len() - advance); | |||
y.1 = TextRange::from_to(y.1.start(), y.1.len() - advance); | |||
} | |||
None |
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.
Good catch!
@@ -59,7 +58,7 @@ impl SyntaxText { | |||
|
|||
pub fn slice<R: private::SyntaxTextRange>(&self, range: R) -> SyntaxText { | |||
let start = range.start().unwrap_or_default(); | |||
let end = range.end().unwrap_or(self.len()); | |||
let end = range.end().unwrap_or_else(|| self.len()); |
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.
This also seems like a false-positive to me: everything here should be inalienable and side-effect and allocation free, so I'd be surprised if there are any significant perf differences. OTOH, readability suffers because of a lambda.
On a more general note, I do appreciate fixing clippy lints (even I don't agree with some particular ones), but it might be prudent to separate "hey, I've run clippy" and "hey, I've completely rewritten the core of this library, It's supper fast now. Oh, and I've added a dozen of unsafe
blocks" pull requests :D
@@ -146,10 +146,10 @@ impl<L: Language> fmt::Display for SyntaxElement<L> { | |||
} | |||
|
|||
impl<L: Language> SyntaxNode<L> { | |||
pub fn new_root(green: GreenNode) -> SyntaxNode<L> { | |||
pub fn new_root(green: Arc<GreenNode>) -> SyntaxNode<L> { |
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.
API wise, it might be a good idea to hide the fact that we use Arc
internally, and just document that GreenNode
is cheap to clone.
@@ -125,7 +124,7 @@ impl FreeList { | |||
for _ in 0..FREE_LIST_LEN { | |||
res.try_push(&mut Rc::new(NodeData { | |||
kind: Kind::Free { next_free: None }, | |||
green: ptr::NonNull::dangling(), |
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.
Hm, ptr::NonNull::danging
seems much more straightforward to me than the dummy node shenanigans. Why do we need this change?
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.
ptr::NonNull::dangling
(as well as ptr::dangling
) requires T: Sized
.
The next PR changes to provide a dangling
fn.
See #35 now. |
This is the result of applying this technique of boxing/deduping
GreenToken
to compressGreenElement
and, as a result, the allocation for aGreenNode
's children. It also applies a minimal flexible array member technique for theGreenNode
's children, allocating them inline.This is as far as the technique can go with using the standard
Arc
andNodeOrToken
.GreenElement = NodeOrToken<Arc<GreenNode>, Arc<GreenToken>>
is 3xusize
large, but can theoretically be niched to 2xusize
. (NB: the same niche optimization can be applied toSyntaxElement
.)I've split this PR up into commits each representing a logical step.
It is possible to optimize size further, but I'd like to propose those in a second PR on top of this one. Remaining potential optimization steps along these lines:
GreenElement
to manually nicheArc<GreenNode>
andArc<GreenToken>
.sizeof(GreenElement)
= 2xusize
.SyntaxElement
to manually nicheSyntaxNode
andSyntaxToken
.sizeof(SyntaxElement)
= 2xusize
.Arc<GreenNode>
to make ptr-to-GreenNode
a thin ptr instead of a fat ptr.GreenElement = NodeOrToken
would be 2xusize
. Manually non-zero-cost nichedGreenElement
(tag in alignment bits) would be 1xusize
.Results in rust-analyzer:
With this branch
Without this branch (5451bfb9)
I can't test allocation pressure on Windows. The way this is right here, it looks like a consistent loss.