From 681022fb9c6099f187397e70ecc74d90ac03947b Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 18 Nov 2021 19:52:18 +0100 Subject: speed up Log::is_boss It is way cheaper to retrieve the correct agent first (especially with the faster agent_by_addr) and then check if it is a boss, rather than iterating over all bosses (which iterates through all characters), and then iterate through the found bosses to check if any address matches. The new code is a bit longer (and doesn't combine the functions as nicely), but it is still readable and more performant - which is more important. --- src/lib.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 53107ff..366739c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ //! While there are legitimate use cases for writing/modification support, they are currently not //! implemented (but might be in a future version). +use num_traits::FromPrimitive; use thiserror::Error; pub mod raw; @@ -102,6 +103,7 @@ mod processing; pub use processing::{process, process_file, process_stream, Compression}; pub mod gamedata; +use gamedata::Boss; pub use gamedata::{EliteSpec, Encounter, GameMode, Profession}; pub mod analyzers; @@ -224,7 +226,15 @@ impl Log { /// Check whether the given address is a boss agent. pub fn is_boss(&self, addr: u64) -> bool { - self.boss_agents().into_iter().any(|a| a.addr() == addr) + let bosses = self + .encounter() + .map(Encounter::bosses) + .unwrap_or(&[] as &[_]); + let agent = self + .agent_by_addr(addr) + .and_then(Agent::as_character) + .and_then(|c| Boss::from_u16(c.id())); + agent.map(|e| bosses.contains(&e)).unwrap_or(false) } /// Returns the encounter id. -- cgit v1.2.3