From b3390aeea68a59e65226d7df878af0ab0626e96d Mon Sep 17 00:00:00 2001 From: Domenic Quirl Date: Wed, 23 Jun 2021 13:42:49 +0200 Subject: [PATCH] speed up green node building by removing copies --- Cargo.toml | 36 +++++++++++++++++++++--------------- src/green/builder.rs | 40 ++++++++++++++++++++++++---------------- src/green/node.rs | 26 +++----------------------- 3 files changed, 48 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b82fef..736c570 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,32 +1,38 @@ [package] -edition = "2018" -name = "cstree" -version = "0.4.0" -authors = ["Domenic Quirl ", "Aleksey Kladov "] +edition = "2018" +name = "cstree" +version = "0.4.0" +authors = [ + "Domenic Quirl ", + "Aleksey Kladov ", +] description = "Library for generic lossless syntax trees" -license = "MIT OR Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/domenicquirl/cstree" -readme = "README.md" +readme = "README.md" + +[profile.release] +debug = true [dependencies] -lasso = "0.5" +lasso = { version="0.5", features=["inline-more"] } text-size = "1.0.0" -fxhash= "0.2.1" -parking_lot= "0.11.1" +fxhash = "0.2.1" +parking_lot = "0.11.1" # Arc triomphe = "0.1.2" [dependencies.serde] -version = "1.0" -optional = true +version = "1.0" +optional = true default-features = false -features = ["derive"] +features = ["derive"] [dev-dependencies] -m_lexer = "0.0.4" -serde_json = "1.0.61" -serde_test = "1.0.119" +m_lexer = "0.0.4" +serde_json = "1.0.61" +serde_test = "1.0.119" crossbeam-utils = "0.8" [features] diff --git a/src/green/builder.rs b/src/green/builder.rs index 973c3d4..a5d753a 100644 --- a/src/green/builder.rs +++ b/src/green/builder.rs @@ -1,6 +1,9 @@ -use std::convert::TryFrom; +use std::{ + convert::TryFrom, + hash::{Hash, Hasher}, +}; -use fxhash::FxHashMap; +use fxhash::{FxHashMap, FxHasher32}; use text_size::TextSize; use crate::{ @@ -132,11 +135,11 @@ where } impl ChildrenIter { - fn new(data: [Option; CHILDREN_CACHE_THRESHOLD], count: usize) -> Self { + fn new() -> Self { ChildrenIter { - data, - idx: 0, - len: count, + data: [None, None, None], + idx: 0, + len: 0, } } } @@ -157,19 +160,24 @@ where } } - let mut data: [Option; CHILDREN_CACHE_THRESHOLD] = [None, None, None]; - let mut count = 0; - - for child in children { - data[count] = Some(child); - count += 1; + let mut new_children = ChildrenIter::new(); + let mut hasher = FxHasher32::default(); + let mut text_len: TextSize = 0.into(); + for (i, child) in children.into_iter().enumerate() { + text_len += child.text_len(); + child.hash(&mut hasher); + new_children.data[i] = Some(child); + new_children.len += 1; } - let children = ChildrenIter::new(data, count); - let head = GreenNodeHead::from_child_iter(kind, children.clone()); + let head = GreenNodeHead { + kind, + text_len, + child_hash: hasher.finish() as u32, + }; self.nodes - .entry(head.clone()) - .or_insert_with(|| GreenNode::from_head_and_children(head, children)) + .entry(head) + .or_insert_with_key(|head| GreenNode::from_head_and_children(head.clone(), new_children)) .clone() } diff --git a/src/green/node.rs b/src/green/node.rs index 1eab4d4..e0b8464 100644 --- a/src/green/node.rs +++ b/src/green/node.rs @@ -15,29 +15,9 @@ use triomphe::{Arc, HeaderWithLength, ThinArc}; #[repr(align(2))] //to use 1 bit for pointer tagging. NB: this is an at-least annotation #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub(super) struct GreenNodeHead { - kind: SyntaxKind, - text_len: TextSize, - child_hash: u32, -} - -impl GreenNodeHead { - #[inline] - pub(super) fn from_child_iter(kind: SyntaxKind, children: I) -> Self - where - I: Iterator, - { - let mut hasher = FxHasher32::default(); - let mut text_len: TextSize = 0.into(); - for child in children { - text_len += child.text_len(); - child.hash(&mut hasher); - } - Self { - kind, - text_len, - child_hash: hasher.finish() as u32, - } - } + pub(super) kind: SyntaxKind, + pub(super) text_len: TextSize, + pub(super) child_hash: u32, } /// Internal node in the immutable "green" tree.