mirror of
https://github.com/tree-sitter/tree-sitter.git
synced 2026-09-10 07:36:22 -04:00
perf(generate): memoize get_production_id
The production info depends only on the production, but was recomputed and deduplicated via a linear deep-equality scan over production_infos for every reduce item in every state. Cache `prod_id` -> `ProductionInfoId`. Wall time reduction 0-3%, peak rss neutral.
This commit is contained in:
parent
d6ae19cc6d
commit
2a81995058
|
|
@ -15,7 +15,7 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
Diagnostic,
|
||||
build_tables::item::{LookaheadSetPool, prec_display},
|
||||
build_tables::item::{LookaheadSetPool, START_PRODUCTION_ID, prec_display},
|
||||
grammars::{LexicalGrammar, PrecedenceEntry, ReservedWordSetId, SyntaxGrammar, VariableType},
|
||||
node_types::VariableInfo,
|
||||
rules::{Associativity, Precedence, Symbol, SymbolType, TokenSet},
|
||||
|
|
@ -73,6 +73,7 @@ struct ParseTableBuilder<'a> {
|
|||
core_ids_by_core: FxHashMap<ParseItemSetCore<'a>, usize>,
|
||||
state_ids_by_item_set: IndexMap<ParseItemSet<'a>, ParseStateId, BuildHasherDefault<FxHasher>>,
|
||||
preceding_symbols_by_id: Vec<SymbolSequence>,
|
||||
production_info_ids_by_prod_id: Vec<Option<ProductionInfoId>>,
|
||||
parse_state_queue: VecDeque<ParseStateQueueEntry>,
|
||||
non_terminal_extra_states: Vec<(Symbol, usize)>,
|
||||
actual_conflicts: FxHashSet<Vec<Symbol>>,
|
||||
|
|
@ -270,6 +271,7 @@ impl<'a> ParseTableBuilder<'a> {
|
|||
state_ids_by_item_set: IndexMap::default(),
|
||||
core_ids_by_core: FxHashMap::default(),
|
||||
preceding_symbols_by_id: Vec::new(),
|
||||
production_info_ids_by_prod_id: vec![None; syntax_grammar.productions.len()],
|
||||
parse_state_queue: VecDeque::new(),
|
||||
actual_conflicts: syntax_grammar.expected_conflicts.iter().cloned().collect(),
|
||||
parse_table: ParseTable {
|
||||
|
|
@ -1138,6 +1140,10 @@ impl<'a> ParseTableBuilder<'a> {
|
|||
}
|
||||
|
||||
fn get_production_id(&mut self, item: &ParseItem) -> ProductionInfoId {
|
||||
debug_assert_ne!(item.prod_id, START_PRODUCTION_ID);
|
||||
if let Some(id) = self.production_info_ids_by_prod_id[item.prod_id as usize] {
|
||||
return id;
|
||||
}
|
||||
let mut production_info = ProductionInfo {
|
||||
alias_sequence: Vec::new(),
|
||||
field_map: BTreeMap::new(),
|
||||
|
|
@ -1191,7 +1197,7 @@ impl<'a> ParseTableBuilder<'a> {
|
|||
item.production(self.syntax_grammar).steps.len();
|
||||
}
|
||||
|
||||
if let Some(index) = self
|
||||
let id = if let Some(index) = self
|
||||
.parse_table
|
||||
.production_infos
|
||||
.iter()
|
||||
|
|
@ -1201,7 +1207,9 @@ impl<'a> ParseTableBuilder<'a> {
|
|||
} else {
|
||||
self.parse_table.production_infos.push(production_info);
|
||||
self.parse_table.production_infos.len() - 1
|
||||
}
|
||||
};
|
||||
self.production_info_ids_by_prod_id[item.prod_id as usize] = Some(id);
|
||||
id
|
||||
}
|
||||
|
||||
fn symbol_name(&self, symbol: Symbol) -> String {
|
||||
|
|
|
|||
Loading…
Reference in a new issue