Skip to content

Commit

Permalink
perf(check): Cuts the max memory use roughly in half on the lisp benc…
Browse files Browse the repository at this point in the history
…hmark

10Mb -> 5Mb
  • Loading branch information
Marwes committed Jan 30, 2019
1 parent 911e252 commit 5b91b6d
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 67 deletions.
109 changes: 103 additions & 6 deletions base/src/fixed.rs
Expand Up @@ -54,6 +54,7 @@ impl<K: Eq + Hash, V> FixedMap<K, V> {
}

pub fn clear(&mut self) {
error!("Clear");
self.map.borrow_mut().clear();
}

Expand Down Expand Up @@ -189,6 +190,26 @@ impl<V> FixedVecMap<V> {
let values = &mut self.values;
self.map.get_mut().get(k).map(move |&key| &mut values[key])
}

pub fn remove(&mut self, k: usize) -> Option<V> {
let values = self.values.values.get_mut();
self.map.get_mut().remove(k).and_then(|(i, j)| {
if values.len() == i as usize + 1 && values[i as usize].len() == j as usize + 1 {
let x = values[i as usize].pop();
if values[i as usize].is_empty() {
values.pop();
}
x
} else {
unimplemented!()
}
})
}

pub fn truncate(&mut self, index: usize) {
self.map.get_mut().retain(|i, _| i < index);
self.values.truncate(index);
}
}

impl<V> Index<usize> for FixedVecMap<V> {
Expand Down Expand Up @@ -240,9 +261,7 @@ impl<T> FixedVec<T> {
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

impl<T> FixedVec<T> {
pub fn iter(&self) -> impl Iterator<Item = &T> {
(0..).scan((), move |_, i| self.get(i))
}
Expand All @@ -254,6 +273,19 @@ impl<T> FixedVec<T> {
None
}
}

pub fn truncate(&mut self, index: usize) {
self.vec.get_mut().truncate(index);
self.values.truncate(index)
}

pub fn pop(&mut self) -> Option<T> {
if self.vec.get_mut().pop().is_some() {
self.values.pop()
} else {
None
}
}
}

impl<T> Index<usize> for FixedVec<T> {
Expand Down Expand Up @@ -289,6 +321,14 @@ impl<T> Buffer<T> {
}
}

fn total_len(&self) -> usize {
self.values
.borrow()
.iter()
.map(|vec| vec.len())
.sum::<usize>()
}

fn push(&self, value: T) -> (u32, u32) {
let mut values = self.values.borrow_mut();
let cap = match values.last() {
Expand All @@ -311,30 +351,87 @@ impl<T> Buffer<T> {
inner.push(value);
(i, j)
}

fn truncate(&mut self, index: usize) {
let mut left = self.total_len() - index;
let values = self.values.get_mut();
while left != 0 {
let inner = values.last_mut().expect("Not values left");
if inner.len() <= left {
left -= inner.len();
values.pop();
} else {
let i = inner.len() - left;
inner.truncate(i);
left = 0;
}
}
}

fn pop(&mut self) -> Option<T> {
let values = self.values.get_mut();
let out = values.last_mut().and_then(|vec| vec.pop());
if out.is_some() {
out
} else {
values.pop();
values.last_mut().and_then(|vec| vec.pop())
}
}
}

impl<T> Index<(u32, u32)> for Buffer<T> {
type Output = T;
fn index(&self, (i, j): (u32, u32)) -> &T {
unsafe { forget_lifetime(&self.values.borrow()[i as usize][j as usize]) }
unsafe {
forget_lifetime(
&self
.values
.borrow()
.get(i as usize)
.and_then(|v| v.get(j as usize))
.unwrap_or_else(|| panic!("Index out of bounds: {:?}", (i, j))),
)
}
}
}

impl<T> IndexMut<(u32, u32)> for Buffer<T> {
fn index_mut(&mut self, (i, j): (u32, u32)) -> &mut T {
&mut self.values.get_mut()[i as usize][j as usize]
self.values
.get_mut()
.get_mut(i as usize)
.and_then(|v| v.get_mut(j as usize))
.unwrap_or_else(|| panic!("Index out of bounds: {:?}", (i, j)))
}
}

impl<T> Index<(u16, u32)> for Buffer<T> {
type Output = T;
fn index(&self, (i, j): (u16, u32)) -> &T {
unsafe { forget_lifetime(&self.values.borrow()[i as usize][j as usize]) }
&self[(i as u32, j)]
}
}

impl<T> IndexMut<(u16, u32)> for Buffer<T> {
fn index_mut(&mut self, (i, j): (u16, u32)) -> &mut T {
&mut self.values.get_mut()[i as usize][j as usize]
&mut self[(i as u32, j)]
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn truncate_buffer() {
let mut buffer = Buffer::new();
for i in 0..10 {
buffer.push(i);
}
buffer.truncate(6);
assert_eq!(buffer.total_len(), 6);
buffer.truncate(2);
assert_eq!(buffer.total_len(), 2);
}
}
37 changes: 32 additions & 5 deletions check/src/implicits.rs
Expand Up @@ -109,12 +109,39 @@ impl Borrow<SymbolRef> for SymbolKey {
type ImplicitBinding = Rc<(Vec<TypedIdent<Symbol, RcType>>, RcType)>;
type ImplicitVector = ::rpds::Vector<ImplicitBinding>;

#[derive(Debug)]
struct Partition<T> {
pub struct Partition<T> {
partition: ::rpds::HashTrieMap<SymbolKey, Partition<T>>,
rest: ::rpds::Vector<T>,
}

impl<T> fmt::Debug for Partition<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Partition")
.field(
"partition",
&format_args!(
"[{}]",
self.partition
.iter()
.format_with(",", |i, f| f(&format_args!("{:?}", i)))
),
)
.field(
"rest",
&format_args!(
"[{}]",
self.rest
.iter()
.format_with(",", |i, f| f(&format_args!("{:?}", i)))
),
)
.finish()
}
}

impl<T> Clone for Partition<T> {
fn clone(&self) -> Self {
Partition {
Expand Down Expand Up @@ -249,8 +276,8 @@ impl Partition<ImplicitBinding> {

#[derive(Clone, Default, Debug)]
pub(crate) struct ImplicitBindings {
partition: Partition<ImplicitBinding>,
definitions: ::rpds::HashTrieSet<Symbol>,
pub partition: Partition<ImplicitBinding>,
pub definitions: ::rpds::HashTrieSet<Symbol>,
}

impl ImplicitBindings {
Expand Down Expand Up @@ -696,7 +723,7 @@ pub struct ImplicitResolver<'a> {
pub(crate) metadata: &'a mut FnvMap<Symbol, Arc<Metadata>>,
environment: &'a TypecheckEnv<Type = RcType>,
pub(crate) implicit_bindings: Vec<ImplicitBindings>,
implicit_vars: ScopedMap<Symbol, ImplicitBindings>,
pub(crate) implicit_vars: ScopedMap<Symbol, ImplicitBindings>,
visited: ScopedMap<Box<[Symbol]>, Box<[RcType]>>,
}

Expand Down
38 changes: 22 additions & 16 deletions check/src/substitution.rs
Expand Up @@ -6,7 +6,7 @@ use crate::base::{
fixed::{FixedVec, FixedVecMap},
kind::ArcKind,
symbol::Symbol,
types::{self, ArcType, Flags, FlagsVisitor, Skolem, Type, TypeContext, Walker},
types::{self, ArcType, Flags, FlagsVisitor, Skolem, Type, TypeContext, TypeExt, Walker},
};
use crate::typ::RcType;

Expand Down Expand Up @@ -270,11 +270,6 @@ where
self.variables.len() as u32
}

pub fn clear(&mut self) {
self.types.clear();
self.variables.clear();
}

pub fn insert(&self, var: u32, t: T) {
match t.get_var() {
Some(_) => ice!(
Expand Down Expand Up @@ -449,16 +444,6 @@ impl<T: Substitutable + PartialEq + Clone> Substitution<T> {
}
Ok(resolved_type.cloned())
}

pub fn unbound_variables(&self, level: u32) -> impl Iterator<Item = &T> {
(level..(self.variables.len() as u32)).filter_map(move |i| {
if self.find_type_for_var(i).is_none() && self.get_level(i) >= level {
Some(&self.variables[i as usize])
} else {
None
}
})
}
}

impl Substitution<RcType> {
Expand All @@ -483,4 +468,25 @@ impl Substitution<RcType> {
pub fn bind_arc(&self, typ: &RcType) -> ArcType {
typ.clone()
}

/// Assumes that all variables < `level` are not unified with anything
pub fn clear_from(&mut self, level: u32) {
self.union = RefCell::new(QuickFindUf::new(0));
let mut u = self.union.borrow_mut();
for _ in 0..level {
u.insert(UnionByLevel {
..UnionByLevel::default()
});
}
self.types.truncate(level as usize);
for t in self.variables.iter().skip(level as usize) {
assert_eq!(
RcType::strong_count(t),
1,
"Variable {} is not unbound at this stage",
t
);
}
self.variables.truncate(level as usize);
}
}

0 comments on commit 5b91b6d

Please sign in to comment.