From 9a8b6747202c5c6b0b506e9736b183ede5f42a28 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Thu, 13 Feb 2025 00:01:20 -0500 Subject: [PATCH] optimize `compute_values` a TON (reduce depth_of calls)... and other stuff --- src/complexagent.rs | 48 ++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/complexagent.rs b/src/complexagent.rs index 57a591f..899406d 100644 --- a/src/complexagent.rs +++ b/src/complexagent.rs @@ -1,3 +1,5 @@ +use either::Either; + use crate::{agent::Agent, board::Board, piece::Piece}; #[derive(Clone)] @@ -137,8 +139,20 @@ impl FutureMoves { } fn compute_values(&mut self) { + // PERF! doing this filtering here previously visited moves reduces time + // spent in `depth_of` from 27.79% -> 2.9% + let mut visited = vec![false; self.arena.len()]; + for depth in (0..=self.current_depth).rev() { let nodes_at_depth: Vec = (0..self.arena.len()) + .filter(|&idx| { + if visited[idx] { + false + } else { + visited[idx] = true; + true + } + }) .filter(|&idx| self.depth_of(idx) == depth) .collect(); @@ -171,21 +185,18 @@ impl FutureMoves { } pub fn best_move(&self) -> Option<(usize, usize)> { - let root_nodes = match self.current_root { - Some(root) => vec![root], - None => self - .arena - .iter() - .enumerate() - .filter_map(|(idx, node)| node.parent.is_none().then_some(idx)) - .collect(), - }; - - root_nodes - .into_iter() - .map(|idx| &self.arena[idx]) - .max_by_key(|x| x.value) - .map(|x| (x.i, x.j)) + (match self.current_root { + Some(root) => Either::Left(vec![root].into_iter()), + None => Either::Right( + self.arena + .iter() + .enumerate() + .filter_map(|(idx, node)| node.parent.is_none().then_some(idx)), + ), + }) + .map(|idx| &self.arena[idx]) + .max_by_key(|x| x.value) + .map(|x| (x.i, x.j)) } pub fn update_root(&mut self, i: usize, j: usize) -> bool { @@ -209,7 +220,12 @@ impl FutureMoves { }; let mut retain = vec![false; self.arena.len()]; - let mut stack = vec![root]; + + // stack is going to be AT MAXIMUM, the size of the array, + // so lets just pre-allocate it + let mut stack = Vec::with_capacity(self.arena.len()); + stack.push(root); + // traverse children of the current root while let Some(idx) = stack.pop() { retain[idx] = true;