Reduce amount of hashing

This commit is contained in:
Laurenz 2023-04-13 14:23:46 +02:00
parent f2732bb7b2
commit 89cf4054d6
10 changed files with 47 additions and 58 deletions

8
Cargo.lock generated
View File

@ -286,9 +286,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "comemo" name = "comemo"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22bf2c21093020535dd771993fedae8dd55393a4258cca501a9b55a962d350a5" checksum = "70b396e6f0a1a7d2c1d588fd8a255a8c30a8edeef65bc96b4afb3fdb8a8bf281"
dependencies = [ dependencies = [
"comemo-macros", "comemo-macros",
"siphasher", "siphasher",
@ -296,9 +296,9 @@ dependencies = [
[[package]] [[package]]
name = "comemo-macros" name = "comemo-macros"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9faa23f4534253fa656b176ff524d5cd7306a6fed3048929f9cc01ab38ab5a5a" checksum = "421c3e125e48959f3b6a18c0d266f3c228f6e28464c73cc44cff24e808fcda2d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -23,7 +23,7 @@ bench = false
typst-macros = { path = "macros" } typst-macros = { path = "macros" }
bitflags = "1" bitflags = "1"
bytemuck = "1" bytemuck = "1"
comemo = "0.2" comemo = "0.2.1"
ecow = "0.1" ecow = "0.1"
flate2 = "1" flate2 = "1"
if_chain = "1" if_chain = "1"

View File

@ -23,7 +23,7 @@ typst = { path = ".." }
typst-library = { path = "../library" } typst-library = { path = "../library" }
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
codespan-reporting = "0.11" codespan-reporting = "0.11"
comemo = "0.2" comemo = "0.2.1"
dirs = "4" dirs = "4"
elsa = "1.7" elsa = "1.7"
memmap2 = "0.5" memmap2 = "0.5"

View File

@ -15,7 +15,7 @@ typst-library = { path = "../library" }
unscanny = "0.1" unscanny = "0.1"
include_dir = "0.7" include_dir = "0.7"
pulldown-cmark = "0.9" pulldown-cmark = "0.9"
comemo = "0.2" comemo = "0.2.1"
serde = "1" serde = "1"
serde_yaml = "0.8" serde_yaml = "0.8"
heck = "0.4" heck = "0.4"

View File

@ -16,7 +16,7 @@ bench = false
[dependencies] [dependencies]
typst = { path = ".." } typst = { path = ".." }
comemo = "0.2" comemo = "0.2.1"
csv = "1" csv = "1"
ecow = "0.1" ecow = "0.1"
hayagriva = "0.3" hayagriva = "0.3"

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter, Write};
use std::iter::Sum; use std::iter::Sum;
use std::ops::{Add, AddAssign}; use std::ops::{Add, AddAssign};
use comemo::Tracked; use comemo::{Prehashed, Tracked};
use ecow::{eco_format, EcoString, EcoVec}; use ecow::{eco_format, EcoString, EcoVec};
use super::{ use super::{
@ -29,8 +29,8 @@ pub struct Content {
enum Attr { enum Attr {
Span(Span), Span(Span),
Field(EcoString), Field(EcoString),
Value(Value), Value(Prehashed<Value>),
Child(Content), Child(Prehashed<Content>),
Styles(Styles), Styles(Styles),
Prepared, Prepared,
Guard(Guard), Guard(Guard),
@ -54,9 +54,11 @@ impl Content {
let Some(first) = iter.next() else { return Self::empty() }; let Some(first) = iter.next() else { return Self::empty() };
let Some(second) = iter.next() else { return first }; let Some(second) = iter.next() else { return first };
let mut content = Content::empty(); let mut content = Content::empty();
content.attrs.push(Attr::Child(first)); content.attrs.push(Attr::Child(Prehashed::new(first)));
content.attrs.push(Attr::Child(second)); content.attrs.push(Attr::Child(Prehashed::new(second)));
content.attrs.extend(iter.map(Attr::Child)); content
.attrs
.extend(iter.map(|child| Attr::Child(Prehashed::new(child))));
content content
} }
@ -164,10 +166,10 @@ impl Content {
Attr::Field(field) => *field == name, Attr::Field(field) => *field == name,
_ => false, _ => false,
}) { }) {
self.attrs.make_mut()[i + 1] = Attr::Value(value.into()); self.attrs.make_mut()[i + 1] = Attr::Value(Prehashed::new(value.into()));
} else { } else {
self.attrs.push(Attr::Field(name)); self.attrs.push(Attr::Field(name));
self.attrs.push(Attr::Value(value.into())); self.attrs.push(Attr::Value(Prehashed::new(value.into())));
} }
} }
@ -285,7 +287,7 @@ impl Content {
self self
} else { } else {
let mut content = Content::new(StyledElem::func()); let mut content = Content::new(StyledElem::func());
content.attrs.push(Attr::Child(self)); content.attrs.push(Attr::Child(Prehashed::new(self)));
content.attrs.push(Attr::Styles(styles)); content.attrs.push(Attr::Styles(styles));
content content
} }
@ -466,11 +468,11 @@ impl Add for Content {
lhs lhs
} }
(true, false) => { (true, false) => {
lhs.attrs.push(Attr::Child(rhs)); lhs.attrs.push(Attr::Child(Prehashed::new(rhs)));
lhs lhs
} }
(false, true) => { (false, true) => {
rhs.attrs.insert(0, Attr::Child(lhs)); rhs.attrs.insert(0, Attr::Child(Prehashed::new(lhs)));
rhs rhs
} }
(false, false) => Self::sequence([lhs, rhs]), (false, false) => Self::sequence([lhs, rhs]),

View File

@ -2,8 +2,10 @@ use std::any::{Any, TypeId};
use std::fmt::{self, Debug, Formatter, Write}; use std::fmt::{self, Debug, Formatter, Write};
use std::iter; use std::iter;
use std::mem; use std::mem;
use std::ptr;
use std::sync::Arc; use std::sync::Arc;
use comemo::Prehashed;
use ecow::{eco_format, eco_vec, EcoString, EcoVec}; use ecow::{eco_format, eco_vec, EcoString, EcoVec};
use super::{Content, ElemFunc, Element, Introspector, Label, Location, Vt}; use super::{Content, ElemFunc, Element, Introspector, Label, Location, Vt};
@ -15,7 +17,7 @@ use crate::util::pretty_array_like;
/// A list of style properties. /// A list of style properties.
#[derive(Default, PartialEq, Clone, Hash)] #[derive(Default, PartialEq, Clone, Hash)]
pub struct Styles(EcoVec<Style>); pub struct Styles(EcoVec<Prehashed<Style>>);
impl Styles { impl Styles {
/// Create a new, empty style list. /// Create a new, empty style list.
@ -34,7 +36,7 @@ impl Styles {
/// style map, `self` contributes the outer values and `value` is the inner /// style map, `self` contributes the outer values and `value` is the inner
/// one. /// one.
pub fn set(&mut self, style: impl Into<Style>) { pub fn set(&mut self, style: impl Into<Style>) {
self.0.push(style.into()); self.0.push(Prehashed::new(style.into()));
} }
/// Remove the style that was last set. /// Remove the style that was last set.
@ -51,20 +53,22 @@ impl Styles {
/// Apply one outer styles. Like [`chain_one`](StyleChain::chain_one), but /// Apply one outer styles. Like [`chain_one`](StyleChain::chain_one), but
/// in-place. /// in-place.
pub fn apply_one(&mut self, outer: Style) { pub fn apply_one(&mut self, outer: Style) {
self.0.insert(0, outer); self.0.insert(0, Prehashed::new(outer));
} }
/// Apply a slice of outer styles. /// Apply a slice of outer styles.
pub fn apply_slice(&mut self, outer: &[Style]) { pub fn apply_slice(&mut self, outer: &[Prehashed<Style>]) {
self.0 = outer.iter().cloned().chain(mem::take(self).0.into_iter()).collect(); self.0 = outer.iter().cloned().chain(mem::take(self).0.into_iter()).collect();
} }
/// Add an origin span to all contained properties. /// Add an origin span to all contained properties.
pub fn spanned(mut self, span: Span) -> Self { pub fn spanned(mut self, span: Span) -> Self {
for entry in self.0.make_mut() { for entry in self.0.make_mut() {
if let Style::Property(property) = entry { entry.update(|entry| {
property.span = Some(span); if let Style::Property(property) = entry {
} property.span = Some(span);
}
});
} }
self self
} }
@ -73,7 +77,7 @@ impl Styles {
/// styles for the given element. /// styles for the given element.
pub fn interruption<T: Element>(&self) -> Option<Option<Span>> { pub fn interruption<T: Element>(&self) -> Option<Option<Span>> {
let func = T::func(); let func = T::func();
self.0.iter().find_map(|entry| match entry { self.0.iter().find_map(|entry| match &**entry {
Style::Property(property) => property.is_of(func).then_some(property.span), Style::Property(property) => property.is_of(func).then_some(property.span),
Style::Recipe(recipe) => recipe.is_of(func).then_some(Some(recipe.span)), Style::Recipe(recipe) => recipe.is_of(func).then_some(Some(recipe.span)),
}) })
@ -82,7 +86,7 @@ impl Styles {
impl From<Style> for Styles { impl From<Style> for Styles {
fn from(entry: Style) -> Self { fn from(entry: Style) -> Self {
Self(eco_vec![entry]) Self(eco_vec![Prehashed::new(entry)])
} }
} }
@ -566,7 +570,7 @@ cast_from_value! {
#[derive(Default, Clone, Copy, Hash)] #[derive(Default, Clone, Copy, Hash)]
pub struct StyleChain<'a> { pub struct StyleChain<'a> {
/// The first link of this chain. /// The first link of this chain.
head: &'a [Style], head: &'a [Prehashed<Style>],
/// The remaining links in the chain. /// The remaining links in the chain.
tail: Option<&'a Self>, tail: Option<&'a Self>,
} }
@ -590,14 +594,6 @@ impl<'a> StyleChain<'a> {
} }
} }
/// Make the given style the first link of the this chain.
pub fn chain_one<'b>(&'b self, style: &'b Style) -> StyleChain<'b> {
StyleChain {
head: std::slice::from_ref(style),
tail: Some(self),
}
}
/// Cast the first value for the given property in the chain. /// Cast the first value for the given property in the chain.
pub fn get<T: Cast>( pub fn get<T: Cast>(
self, self,
@ -733,16 +729,6 @@ impl<'a> StyleChain<'a> {
fn pop(&mut self) { fn pop(&mut self) {
*self = self.tail.copied().unwrap_or_default(); *self = self.tail.copied().unwrap_or_default();
} }
/// Whether two style chains contain the same pointers.
fn ptr_eq(self, other: Self) -> bool {
std::ptr::eq(self.head, other.head)
&& match (self.tail, other.tail) {
(Some(a), Some(b)) => std::ptr::eq(a, b),
(None, None) => true,
_ => false,
}
}
} }
impl Debug for StyleChain<'_> { impl Debug for StyleChain<'_> {
@ -756,13 +742,18 @@ impl Debug for StyleChain<'_> {
impl PartialEq for StyleChain<'_> { impl PartialEq for StyleChain<'_> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.ptr_eq(*other) || crate::util::hash128(self) == crate::util::hash128(other) ptr::eq(self.head, other.head)
&& match (self.tail, other.tail) {
(Some(a), Some(b)) => ptr::eq(a, b),
(None, None) => true,
_ => false,
}
} }
} }
/// An iterator over the entries in a style chain. /// An iterator over the entries in a style chain.
struct Entries<'a> { struct Entries<'a> {
inner: std::slice::Iter<'a, Style>, inner: std::slice::Iter<'a, Prehashed<Style>>,
links: Links<'a>, links: Links<'a>,
} }
@ -787,7 +778,7 @@ impl<'a> Iterator for Entries<'a> {
struct Links<'a>(Option<StyleChain<'a>>); struct Links<'a>(Option<StyleChain<'a>>);
impl<'a> Iterator for Links<'a> { impl<'a> Iterator for Links<'a> {
type Item = &'a [Style]; type Item = &'a [Prehashed<Style>];
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let StyleChain { head, tail } = self.0?; let StyleChain { head, tail } = self.0?;

View File

@ -110,9 +110,7 @@ impl Source {
pub fn edit(&mut self, replace: Range<usize>, with: &str) -> Range<usize> { pub fn edit(&mut self, replace: Range<usize>, with: &str) -> Range<usize> {
let start_byte = replace.start; let start_byte = replace.start;
let start_utf16 = self.byte_to_utf16(replace.start).unwrap(); let start_utf16 = self.byte_to_utf16(replace.start).unwrap();
let mut text = std::mem::take(&mut self.text).into_inner(); self.text.update(|text| text.replace_range(replace.clone(), with));
text.replace_range(replace.clone(), with);
self.text = Prehashed::new(text);
// Remove invalidated line starts. // Remove invalidated line starts.
let line = self.byte_to_line(start_byte).unwrap(); let line = self.byte_to_line(start_byte).unwrap();
@ -128,10 +126,8 @@ impl Source {
.extend(lines_from(start_byte, start_utf16, &self.text[start_byte..])); .extend(lines_from(start_byte, start_utf16, &self.text[start_byte..]));
// Incrementally reparse the replaced range. // Incrementally reparse the replaced range.
let mut root = std::mem::take(&mut self.root).into_inner(); self.root
let range = reparse(&mut root, &self.text, replace, with.len()); .update(|root| reparse(root, &self.text, replace, with.len()))
self.root = Prehashed::new(root);
range
} }
/// Get the length of the file in UTF-8 encoded bytes. /// Get the length of the file in UTF-8 encoded bytes.

View File

@ -8,7 +8,7 @@ publish = false
[dev-dependencies] [dev-dependencies]
typst = { path = ".." } typst = { path = ".." }
typst-library = { path = "../library" } typst-library = { path = "../library" }
comemo = "0.2" comemo = "0.2.1"
elsa = "1.7" elsa = "1.7"
iai = { git = "https://github.com/reknih/iai" } iai = { git = "https://github.com/reknih/iai" }
once_cell = "1" once_cell = "1"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB