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

Use of SmallVec in PluralRules Parser/AST #193

Closed
zbraniecki opened this issue Aug 1, 2020 · 2 comments
Closed

Use of SmallVec in PluralRules Parser/AST #193

zbraniecki opened this issue Aug 1, 2020 · 2 comments
Labels
A-performance Area: Performance (CPU, Memory) C-pluralrules Component: Plural rules help wanted Issue needs an assignee R-obsolete Resolution: This issue is no longer relevant T-enhancement Type: Nice-to-have but not required

Comments

@zbraniecki
Copy link
Member

You have a lot of boxes, which means a lot of mallocs. This is probably fine, but I wonder if smallvec would be useful, since I expect that most of these lists will be between 0 and 2 elements long, with a few going up to 5 or 6.

Originally posted by @sffc in https://github.com/unicode-org/icu4x/diffs/22

@zbraniecki
Copy link
Member Author

I have the following patch that tests that:

diff --git a/components/pluralrules/Cargo.toml b/components/pluralrules/Cargo.toml
index 58ed6f8..c7e8aa4 100644
--- a/components/pluralrules/Cargo.toml
+++ b/components/pluralrules/Cargo.toml
@@ -20,6 +20,7 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
 serde_json = {version = "1.0", optional = true }
 bincode = { version = "1.3", optional = true }
 serde-tuple-vec-map = { version = "1.0", optional = true }
+smallvec = "1.0"
 
 [dev-dependencies]
 criterion = "0.3"
diff --git a/components/pluralrules/src/rules/ast.rs b/components/pluralrules/src/rules/ast.rs
index b90bc33..3386d63 100644
--- a/components/pluralrules/src/rules/ast.rs
+++ b/components/pluralrules/src/rules/ast.rs
@@ -34,6 +34,7 @@
 //! [`PluralCategory`]: ../enum.PluralCategory.html
 //! [`parse`]: ../fn.parse.html
 //! [`test_condition`]: ../fn.test_condition.html
+use smallvec::SmallVec;
 use std::ops::RangeInclusive;
 
 #[derive(Debug, Clone, PartialEq)]
@@ -76,7 +77,7 @@ pub struct Rule {
 /// )
 /// ```
 #[derive(Debug, Clone, PartialEq)]
-pub struct Condition(pub Box<[AndCondition]>);
+pub struct Condition(pub SmallVec<[AndCondition; 2]>);
 
 /// An incomplete AST representation of a plural rule. Comprises a vector of Relations.
 ///
@@ -114,7 +115,7 @@ pub struct Condition(pub Box<[AndCondition]>);
 ///
 /// ```
 #[derive(Debug, Clone, PartialEq)]
-pub struct AndCondition(pub Box<[Relation]>);
+pub struct AndCondition(pub SmallVec<[Relation; 2]>);
 
 /// An incomplete AST representation of a plural rule. Comprises an Expression, an Operator, and a RangeList.
 ///
@@ -245,7 +246,7 @@ pub enum Operand {
 /// ]));
 /// ```
 #[derive(Debug, Clone, PartialEq)]
-pub struct RangeList(pub Box<[RangeListItem]>);
+pub struct RangeList(pub SmallVec<[RangeListItem; 2]>);
 
 /// An enum of items that appear in a RangeList: Range or a Value.
 ///
diff --git a/components/pluralrules/src/rules/parser.rs b/components/pluralrules/src/rules/parser.rs
index 0357a89..b83a80a 100644
--- a/components/pluralrules/src/rules/parser.rs
+++ b/components/pluralrules/src/rules/parser.rs
@@ -1,6 +1,7 @@
 use super::ast;
 use super::lexer::{Lexer, Token};
 use std::iter::Peekable;
+use smallvec::SmallVec;
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum ParserError {
@@ -47,12 +48,12 @@ impl<'p> Parser<'p> {
     }
 
     fn parse(mut self) -> Result<ast::Condition, ParserError> {
-        let mut result = vec![];
+        let mut result = SmallVec::new();
 
         if let Some(cond) = self.get_and_condition()? {
             result.push(cond);
         } else {
-            return Ok(ast::Condition(result.into_boxed_slice()));
+            return Ok(ast::Condition(result));
         }
 
         while self.take_if(Token::Or) {
@@ -63,12 +64,13 @@ impl<'p> Parser<'p> {
             }
         }
         // If lexer is not done, error?
-        Ok(ast::Condition(result.into_boxed_slice()))
+        Ok(ast::Condition(result))
     }
 
     fn get_and_condition(&mut self) -> Result<Option<ast::AndCondition>, ParserError> {
         if let Some(relation) = self.get_relation()? {
-            let mut rel = vec![relation];
+            let mut rel = SmallVec::new();
+            rel.push(relation);
 
             while self.take_if(Token::And) {
                 if let Some(relation) = self.get_relation()? {
@@ -77,7 +79,7 @@ impl<'p> Parser<'p> {
                     return Err(ParserError::ExpectedRelation);
                 }
             }
-            Ok(Some(ast::AndCondition(rel.into_boxed_slice())))
+            Ok(Some(ast::AndCondition(rel)))
         } else {
             Ok(None)
         }
@@ -115,14 +117,14 @@ impl<'p> Parser<'p> {
     }
 
     fn get_range_list(&mut self) -> Result<ast::RangeList, ParserError> {
-        let mut range_list = Vec::with_capacity(1);
+        let mut range_list = SmallVec::new();
         loop {
             range_list.push(self.get_range_list_item()?);
             if !self.take_if(Token::Comma) {
                 break;
             }
         }
-        Ok(ast::RangeList(range_list.into_boxed_slice()))
+        Ok(ast::RangeList(range_list))
     }
 
     fn take_if(&mut self, token: Token) -> bool {

@zbraniecki zbraniecki added A-performance Area: Performance (CPU, Memory) C-pluralrules Component: Plural rules labels Aug 1, 2020
@sffc sffc added T-enhancement Type: Nice-to-have but not required help wanted Issue needs an assignee backlog labels Aug 14, 2020
@sffc
Copy link
Member

sffc commented Nov 10, 2022

We no longer use runtime allocations in PluralRules.

@sffc sffc closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2022
@sffc sffc added the R-obsolete Resolution: This issue is no longer relevant label Nov 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-performance Area: Performance (CPU, Memory) C-pluralrules Component: Plural rules help wanted Issue needs an assignee R-obsolete Resolution: This issue is no longer relevant T-enhancement Type: Nice-to-have but not required
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants