Reduce the size of the FramesEntry struct and bump edition

This commit is contained in:
Martin Haug 2021-12-13 15:15:12 +01:00
parent 1b67887db0
commit 738ff7e1f5
3 changed files with 34 additions and 28 deletions

View File

@ -2,7 +2,7 @@
name = "typst" name = "typst"
version = "0.1.0" version = "0.1.0"
authors = ["The Typst Project Developers"] authors = ["The Typst Project Developers"]
edition = "2018" edition = "2021"
[features] [features]
default = ["cli", "fs", "layout-cache"] default = ["cli", "fs", "layout-cache"]

View File

@ -8,8 +8,7 @@ use super::{Constrained, Regions};
use crate::frame::Frame; use crate::frame::Frame;
use crate::geom::Scalar; use crate::geom::Scalar;
const TEMP_LEN: usize = 5; const TEMP_LEN: usize = 4;
const TEMP_LAST: usize = TEMP_LEN - 1;
/// Caches layouting artifacts. /// Caches layouting artifacts.
/// ///
@ -101,13 +100,13 @@ impl LayoutCache {
entry.used_cycles += 1; entry.used_cycles += 1;
} }
let last = entry.temperature[TEMP_LAST]; let last = *entry.temperature.last().unwrap();
for i in (1 .. TEMP_LEN).rev() { for i in (1 .. TEMP_LEN).rev() {
entry.temperature[i] = entry.temperature[i - 1]; entry.temperature[i] = entry.temperature[i - 1];
} }
entry.temperature[0] = 0; entry.temperature[0] = 0;
entry.temperature[TEMP_LAST] += last; entry.ancient_hits += last as usize;
entry.age += 1; entry.age += 1;
} }
@ -199,9 +198,10 @@ pub struct FramesEntry {
/// For how long the element already exists. /// For how long the element already exists.
age: usize, age: usize,
/// How much the element was accessed during the last five compilations, the /// How much the element was accessed during the last five compilations, the
/// most recent one being the first element. The last element will collect /// most recent one being the first element.
/// all usages that are farther in the past. temperature: [u8; TEMP_LEN],
temperature: [usize; TEMP_LEN], /// All past usages that do not fit in the temperature array.
ancient_hits: usize,
/// Amount of cycles in which the element has been used at all. /// Amount of cycles in which the element has been used at all.
used_cycles: usize, used_cycles: usize,
} }
@ -214,6 +214,7 @@ impl FramesEntry {
level, level,
age: 1, age: 1,
temperature: [0; TEMP_LEN], temperature: [0; TEMP_LEN],
ancient_hits: 0,
used_cycles: 0, used_cycles: 0,
} }
} }
@ -222,7 +223,7 @@ impl FramesEntry {
/// them if so. /// them if so.
pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> { pub fn lookup(&mut self, regions: &Regions) -> Option<Vec<Constrained<Rc<Frame>>>> {
self.check(regions).then(|| { self.check(regions).then(|| {
self.temperature[0] += 1; self.temperature[0] = self.temperature[0].saturating_add(1);
self.frames.clone() self.frames.clone()
}) })
} }
@ -254,7 +255,7 @@ impl FramesEntry {
/// Get the total amount of hits over the lifetime of this item. /// Get the total amount of hits over the lifetime of this item.
pub fn hits(&self) -> usize { pub fn hits(&self) -> usize {
self.temperature.iter().sum() self.temperature.into_iter().map(usize::from).sum::<usize>() + self.ancient_hits
} }
/// The amount of consecutive cycles in which this item has not been used. /// The amount of consecutive cycles in which this item has not been used.
@ -280,7 +281,7 @@ impl FramesEntry {
let mut last = None; let mut last = None;
let mut all_same = true; let mut all_same = true;
for (i, &temp) in self.temperature[.. TEMP_LAST].iter().enumerate() { for (i, &temp) in self.temperature.iter().enumerate() {
if temp == 0 && !all_zeros { if temp == 0 && !all_zeros {
sparse = true; sparse = true;
} }
@ -310,16 +311,16 @@ impl FramesEntry {
last = Some(temp); last = Some(temp);
} }
if self.age >= TEMP_LEN && self.age - TEMP_LAST < self.temperature[TEMP_LAST] { if self.age > TEMP_LEN && self.age - TEMP_LEN <= self.ancient_hits {
multi_use = true; multi_use = true;
} }
if self.temperature[TEMP_LAST] > 0 { if self.ancient_hits > 0 {
all_zeros = false; all_zeros = false;
} }
PatternProperties { PatternProperties {
mature: self.age >= TEMP_LEN, mature: self.age > TEMP_LEN,
hit: self.temperature[0] >= 1, hit: self.temperature[0] >= 1,
top_level: self.level == 0, top_level: self.level == 0,
all_zeros, all_zeros,
@ -421,19 +422,22 @@ mod tests {
let entry = cache.frames.get(&0).unwrap().first().unwrap(); let entry = cache.frames.get(&0).unwrap().first().unwrap();
assert_eq!(entry.age(), 1); assert_eq!(entry.age(), 1);
assert_eq!(entry.temperature, [0, 0, 0, 0, 0]); assert_eq!(entry.temperature, [0, 0, 0, 0]);
assert_eq!(entry.ancient_hits, 0);
assert_eq!(entry.used_cycles, 0); assert_eq!(entry.used_cycles, 0);
assert_eq!(entry.level, 0); assert_eq!(entry.level, 0);
cache.get(0, &regions).unwrap(); cache.get(0, &regions).unwrap();
let entry = cache.frames.get(&0).unwrap().first().unwrap(); let entry = cache.frames.get(&0).unwrap().first().unwrap();
assert_eq!(entry.age(), 1); assert_eq!(entry.age(), 1);
assert_eq!(entry.temperature, [1, 0, 0, 0, 0]); assert_eq!(entry.temperature, [1, 0, 0, 0]);
assert_eq!(entry.ancient_hits, 0);
cache.turnaround(); cache.turnaround();
let entry = cache.frames.get(&0).unwrap().first().unwrap(); let entry = cache.frames.get(&0).unwrap().first().unwrap();
assert_eq!(entry.age(), 2); assert_eq!(entry.age(), 2);
assert_eq!(entry.temperature, [0, 1, 0, 0, 0]); assert_eq!(entry.temperature, [0, 1, 0, 0]);
assert_eq!(entry.ancient_hits, 0);
assert_eq!(entry.used_cycles, 1); assert_eq!(entry.used_cycles, 1);
cache.get(0, &regions).unwrap(); cache.get(0, &regions).unwrap();
@ -443,7 +447,8 @@ mod tests {
let entry = cache.frames.get(&0).unwrap().first().unwrap(); let entry = cache.frames.get(&0).unwrap().first().unwrap();
assert_eq!(entry.age(), 6); assert_eq!(entry.age(), 6);
assert_eq!(entry.temperature, [0, 0, 0, 0, 2]); assert_eq!(entry.temperature, [0, 0, 0, 0]);
assert_eq!(entry.ancient_hits, 2);
assert_eq!(entry.used_cycles, 2); assert_eq!(entry.used_cycles, 2);
} }

View File

@ -27,7 +27,7 @@ macro_rules! node {
($(#[$attr:meta])* $name:ident: $variant:ident) => { ($(#[$attr:meta])* $name:ident: $variant:ident) => {
node!{$(#[$attr])* $name: NodeKind::$variant} node!{$(#[$attr])* $name: NodeKind::$variant}
}; };
($(#[$attr:meta])* $name:ident: $($variant:pat)|*) => { ($(#[$attr:meta])* $name:ident: $variants:pat) => {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[repr(transparent)] #[repr(transparent)]
$(#[$attr])* $(#[$attr])*
@ -35,7 +35,7 @@ macro_rules! node {
impl TypedNode for $name { impl TypedNode for $name {
fn from_red(node: RedRef) -> Option<Self> { fn from_red(node: RedRef) -> Option<Self> {
if matches!(node.kind(), $($variant)|*) { if matches!(node.kind(), $variants) {
Some(Self(node.own())) Some(Self(node.own()))
} else { } else {
None None
@ -274,15 +274,16 @@ impl TypedNode for Expr {
impl Expr { impl Expr {
/// Whether the expression can be shortened in markup with a hashtag. /// Whether the expression can be shortened in markup with a hashtag.
pub fn has_short_form(&self) -> bool { pub fn has_short_form(&self) -> bool {
matches!(self, matches!(
self,
Self::Ident(_) Self::Ident(_)
| Self::Call(_) | Self::Call(_)
| Self::Let(_) | Self::Let(_)
| Self::If(_) | Self::If(_)
| Self::While(_) | Self::While(_)
| Self::For(_) | Self::For(_)
| Self::Import(_) | Self::Import(_)
| Self::Include(_) | Self::Include(_)
) )
} }
} }