]> Repositorios git - scryer-prolog.git/commitdiff
switch from Integer to u128
authorSkgland <[email protected]>
Sat, 21 Mar 2026 12:36:40 +0000 (13:36 +0100)
committerSkgland <[email protected]>
Sat, 21 Mar 2026 12:36:40 +0000 (13:36 +0100)
- 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%

src/machine/dispatch.rs
src/machine/machine_state.rs
src/machine/mod.rs
src/machine/system_calls.rs
src/parser/ast.rs

index 0209268ad2326e605dfe88ce74c31e3642ff5513..33e9db1a2ba57ac459994b2d8586688fa22c1bff 100644 (file)
@@ -4256,12 +4256,12 @@ impl Machine {
                         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);
                     }
index 577782409d8015dd9cc8c7f8ec3a72755a254c97..a5ba3eff5f2c721d33b5adb9ca16dbbed81583e1 100644 (file)
@@ -16,7 +16,6 @@ use crate::parser::ast::*;
 use crate::read::TermWriteResult;
 use crate::types::*;
 
-use crate::parser::dashu::Integer;
 
 use indexmap::IndexMap;
 
@@ -1112,23 +1111,23 @@ impl MachineState {
 #[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() {
@@ -1136,23 +1135,23 @@ impl CWIL {
             _ => 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;
     }
index 859290a423384fa8437e1b64f1a29ef83a417583..903dad2daa543522ce1575a463cdc8cc69a85e9c 100644 (file)
@@ -237,7 +237,6 @@ impl Machine {
         self.machine_st
             .cwil
             .global_count
-            .clone()
             .try_into()
             .unwrap()
     }
index 026b19672d6f48e45cd8c02fabd13f596a236ff6..1867196b7474be50cc75b63cde71bc01029ad272 100644 (file)
@@ -6141,8 +6141,8 @@ impl Machine {
         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);
@@ -6153,21 +6153,21 @@ impl Machine {
         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);
         }
     }
@@ -6321,11 +6321,11 @@ impl Machine {
         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);
         }
     }
index 8c71cc709026dd267cba18d308fd635d0bff6407..dbfd011e25c47534d086aec3541db4de69c1d0f7 100644 (file)
@@ -608,6 +608,7 @@ mod private {
     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 {}