- u128 is only 16 bytes instead of 24
- incrementing u128 does not involve heap allocations
- u128 should be sufficent
it would take more than 2 sextilion years to overflow if we would be incrementing it every tick at 5GHz
i.e. 2^128-1 / 5 GHz / 60 / 60 / 24 / 356 > 2 sextilion
before this ~3.2% of the execution time of the program in https://github.com/mthom/scryer-prolog/issues/3265#issuecomment-
4103176469 was spend in the increment_call_count function, after this change it's down to 0.3%
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallInferenceCount => {
- let global_count = self.machine_st.cwil.global_count.clone();
+ let global_count = self.machine_st.cwil.global_count;
self.inference_count(self.machine_st.registers[1], global_count);
step_or_fail!(self.machine_st, self.machine_st.p += 1);
}
&Instruction::ExecuteInferenceCount => {
- let global_count = self.machine_st.cwil.global_count.clone();
+ let global_count = self.machine_st.cwil.global_count;
self.inference_count(self.machine_st.registers[1], global_count);
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
}
use crate::read::TermWriteResult;
use crate::types::*;
-use crate::parser::dashu::Integer;
use indexmap::IndexMap;
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug)]
pub(crate) struct CWIL {
- local_count: Integer,
- pub(crate) global_count: Integer,
- limits: Vec<(Integer, usize)>,
+ local_count: u128,
+ pub(crate) global_count: u128,
+ limits: Vec<(u128, usize)>,
pub(crate) inference_limit_exceeded: bool,
}
impl CWIL {
pub(crate) fn new() -> Self {
CWIL {
- local_count: Integer::from(0),
- global_count: Integer::from(0),
+ local_count: 0,
+ global_count: 0,
limits: vec![],
inference_limit_exceeded: false,
}
}
- pub(crate) fn add_limit(&mut self, mut limit: Integer, block: usize) -> &Integer {
+ pub(crate) fn add_limit(&mut self, mut limit: u128, block: usize) -> u128 {
limit += &self.local_count;
match self.limits.last() {
_ => self.limits.push((limit, block)),
}
- &self.local_count
+ self.local_count
}
#[inline(always)]
- pub(crate) fn remove_limit(&mut self, block: usize) -> &Integer {
+ pub(crate) fn remove_limit(&mut self, block: usize) -> u128 {
if let Some((_, bl)) = self.limits.last() {
if bl == &block {
self.limits.pop();
}
}
- &self.local_count
+ self.local_count
}
#[inline(always)]
pub(crate) fn reset(&mut self) {
- self.local_count = Integer::from(0);
+ self.local_count = 0;
self.limits.clear();
self.inference_limit_exceeded = false;
}
self.machine_st
.cwil
.global_count
- .clone()
.try_into()
.unwrap()
}
let a2 = self.deref_register(2);
let n = match Number::try_from((a2, &self.machine_st.arena.f64_tbl)) {
- Ok(Number::Fixnum(bp)) => Integer::from(bp.get_num() as usize),
- Ok(Number::Integer(n)) => (*n).clone(),
+ Ok(Number::Fixnum(bp)) => bp.get_num() as u128,
+ Ok(Number::Integer(n)) => u128::try_from(&*n).unwrap(),
_ => {
let stub = functor_stub(atom!("call_with_inference_limit"), 3);
let err = self.machine_st.type_error(ValidType::Integer, a2);
let bp = unsafe { a1.to_fixnum_or_cut_point_unchecked() }.get_num() as usize;
let a3 = self.deref_register(3);
- let count = self.machine_st.cwil.add_limit(n, bp).clone();
+ let count = self.machine_st.cwil.add_limit(n, bp);
self.inference_count(a3, count);
Ok(())
}
#[inline(always)]
- pub(crate) fn inference_count(&mut self, count_var: HeapCellValue, count: Integer) {
- if let Some(value) = <&Integer as TryInto<i64>>::try_into(&count)
+ pub(crate) fn inference_count(&mut self, count_var: HeapCellValue, count: u128) {
+ if let Some(value) = TryInto::<i64>::try_into(count)
.ok()
.and_then(|i| Fixnum::build_with_checked(i).ok())
{
self.machine_st.unify_fixnum(value, count_var);
} else {
- let count = arena_alloc!(count, &mut self.machine_st.arena);
+ let count = arena_alloc!(Integer::from(count), &mut self.machine_st.arena);
self.machine_st.unify_big_int(count, count_var);
}
}
let a2 = self.deref_register(2);
let block = unsafe { a1.to_fixnum_or_cut_point_unchecked() }.get_num() as usize;
- let count = self.machine_st.cwil.remove_limit(block).clone();
- if let Ok(value) = Fixnum::build_with_checked(&count) {
+ let count = self.machine_st.cwil.remove_limit(block);
+ if let Ok(value) = Fixnum::build_with_checked(count) {
self.machine_st.unify_fixnum(value, a2);
} else {
- let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
+ let count = arena_alloc!(Integer::from(count), &mut self.machine_st.arena);
self.machine_st.unify_big_int(count, a2);
}
}
impl<T: FitsInFixnumSeal> MightNotFitInFixnumSeal for T {}
impl MightNotFitInFixnumSeal for i64 {}
impl MightNotFitInFixnumSeal for u64 {}
+ impl MightNotFitInFixnumSeal for u128 {}
impl MightNotFitInFixnumSeal for &Integer {}
impl MightNotFitInFixnumSeal for Integer {}
impl MightNotFitInFixnumSeal for usize {}