From 712d356b969540c7f09fad08c141e3c6aadde00f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 20 Apr 2024 16:07:14 +0200 Subject: Introduce TaskIDRef type A borrowed version of a TaskID, allowing to avoid allocations in some places. Tasks are now stored in a two-level map in Context. --- crates/rebel-common/src/types.rs | 21 ++++++++++++++ crates/rebel/src/context.rs | 63 +++++++++++++++++++++++++--------------- crates/rebel/src/recipe.rs | 23 ++++++++------- crates/rebel/src/resolve.rs | 6 ++-- 4 files changed, 76 insertions(+), 37 deletions(-) diff --git a/crates/rebel-common/src/types.rs b/crates/rebel-common/src/types.rs index 2a06275..d3beb70 100644 --- a/crates/rebel-common/src/types.rs +++ b/crates/rebel-common/src/types.rs @@ -13,7 +13,28 @@ pub struct TaskID { pub task: String, } +impl TaskID { + pub fn as_ref(&self) -> TaskIDRef<'_> { + TaskIDRef { + recipe: &self.recipe, + task: &self.task, + } + } +} + impl Display for TaskID { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.as_ref().fmt(f) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct TaskIDRef<'a> { + pub recipe: &'a str, + pub task: &'a str, +} + +impl<'a> Display for TaskIDRef<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}::{}", self.recipe, self.task) } diff --git a/crates/rebel/src/context.rs b/crates/rebel/src/context.rs index fa24399..bf16546 100644 --- a/crates/rebel/src/context.rs +++ b/crates/rebel/src/context.rs @@ -12,7 +12,7 @@ use std::{ use rebel_common::{ error::{self, Contextualizable}, string_hash::ArchiveHash, - types::TaskID, + types::TaskIDRef, }; use rebel_parse::{self as parse, TaskFlags}; @@ -32,7 +32,7 @@ pub enum ErrorKind<'a> { #[derive(Debug, Clone, Copy)] pub struct Error<'a> { - pub task: &'a TaskID, + pub task: TaskIDRef<'a>, pub kind: ErrorKind<'a>, } @@ -65,7 +65,7 @@ pub type Result<'a, T> = result::Result>; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TaskRef<'ctx> { - pub id: &'ctx TaskID, + pub id: TaskIDRef<'ctx>, pub args: Rc, } @@ -144,12 +144,15 @@ fn platform_relation(args: &TaskArgs, from: &str, to: &str) -> Option, globals: TaskArgs, - tasks: HashMap>, + tasks: HashMap>>, rootfs: (ArchiveHash, String), } impl Context { - pub fn new(mut tasks: HashMap>, pins: Pins) -> error::Result { + pub fn new( + mut tasks: HashMap>>, + pins: Pins, + ) -> error::Result { let platforms: HashMap<_, _> = [ arg( "build", @@ -212,7 +215,7 @@ impl Context { } fn add_rootfs_tasks( - tasks: &mut HashMap>, + tasks: &mut HashMap>>, provides: Vec, globals: &TaskArgs, ) -> error::Result<()> { @@ -255,10 +258,9 @@ impl Context { task_def.priority = i32::MAX; tasks - .entry(TaskID { - recipe: recipe.to_string(), - task: task.to_string(), - }) + .entry(recipe) + .or_default() + .entry(task) .or_default() .push(task_def); } @@ -293,9 +295,12 @@ impl Context { .max_by(|task1, task2| Self::compare_tasks(task1, task2)) } - fn get_with_args<'a>(&self, id: &'a TaskID, args: &TaskArgs) -> Result<'a, &TaskDef> { - self.tasks - .get(id) + fn get_by_ref(&self, id: TaskIDRef) -> Option<&[TaskDef]> { + Some(self.tasks.get(id.recipe)?.get(id.task)?) + } + + fn get_with_args<'a>(&self, id: TaskIDRef<'a>, args: &TaskArgs) -> Result<'a, &TaskDef> { + self.get_by_ref(id) .and_then(|tasks| Self::select_task(tasks, args)) .ok_or(Error { task: id, @@ -307,7 +312,7 @@ impl Context { self.get_with_args(task.id, task.args.as_ref()) } - fn task_ref<'ctx>(&'ctx self, id: &'ctx TaskID, args: &TaskArgs) -> Result { + fn task_ref<'ctx>(&'ctx self, id: TaskIDRef<'ctx>, args: &TaskArgs) -> Result { let task_def = self.get_with_args(id, args)?; let mut arg_def: HashMap<_, _> = task_def.args.iter().map(|(k, &v)| (k, v)).collect(); @@ -362,14 +367,22 @@ impl Context { .ok() .context("Invalid task syntax")?; - let recipe = parsed.id.recipe.to_string(); - let task = parsed.id.task.to_string(); + let id = TaskIDRef { + recipe: parsed.id.recipe, + task: parsed.id.task, + }; - let id = TaskID { recipe, task }; - let (ctx_id, _) = self + let (ctx_recipe, recipe_tasks) = self .tasks - .get_key_value(&id) + .get_key_value(id.recipe) + .with_context(|| format!("Task {} not found", id))?; + let (ctx_task, _) = recipe_tasks + .get_key_value(id.task) .with_context(|| format!("Task {} not found", id))?; + let ctx_id = TaskIDRef { + recipe: ctx_recipe, + task: ctx_task, + }; let mut args = self.globals.clone(); @@ -397,7 +410,7 @@ impl Context { } fn map_args<'ctx, 'args>( - task: &'ctx TaskID, + task: TaskIDRef<'ctx>, mapping: &'ctx ArgMapping, args: &'args TaskArgs, build_dep: bool, @@ -425,8 +438,9 @@ impl Context { } fn parent_ref<'ctx>(&'ctx self, dep: &'ctx ParentDep, args: &TaskArgs) -> Result { - let mapped_args = Context::map_args(&dep.dep.id, &dep.dep.args, args, false)?; - self.task_ref(&dep.dep.id, mapped_args.as_ref()) + let id = dep.dep.id.as_ref(); + let mapped_args = Context::map_args(id, &dep.dep.args, args, false)?; + self.task_ref(id, mapped_args.as_ref()) } pub fn output_ref<'ctx>( @@ -435,9 +449,10 @@ impl Context { args: &TaskArgs, build_dep: bool, ) -> Result> { - let mapped_args = Context::map_args(&dep.dep.id, &dep.dep.args, args, build_dep)?; + let id = dep.dep.id.as_ref(); + let mapped_args = Context::map_args(id, &dep.dep.args, args, build_dep)?; Ok(OutputRef { - task: self.task_ref(&dep.dep.id, mapped_args.as_ref())?, + task: self.task_ref(id, mapped_args.as_ref())?, output: &dep.output, }) } diff --git a/crates/rebel/src/recipe.rs b/crates/rebel/src/recipe.rs index fd5367a..24b4bff 100644 --- a/crates/rebel/src/recipe.rs +++ b/crates/rebel/src/recipe.rs @@ -74,24 +74,25 @@ fn recipe_name(path: &Path) -> Option<&str> { } fn handle_recipe_tasks( - tasks: &mut HashMap>, + tasks: &mut HashMap>>, recipe_tasks: HashMap, meta: &TaskMeta, ) { + let task_map = match tasks.get_mut(&meta.recipe) { + Some(task_map) => task_map, + None => tasks.entry(meta.recipe.clone()).or_default(), + }; + for (label, mut task) in recipe_tasks { - let task_id = TaskID { - recipe: meta.recipe.clone(), - task: label, - }; task.meta = meta.clone(); - tasks.entry(task_id).or_default().push(task); + task_map.entry(label).or_default().push(task); } } fn read_recipe_tasks( path: &Path, basename: &str, - tasks: &mut HashMap>, + tasks: &mut HashMap>>, ) -> Result { let recipe_def = CURRENT_RECIPE.set(basename, || read_yaml::(path))?; @@ -120,7 +121,7 @@ fn read_subrecipe_tasks( basename: &str, recipename: &str, recipe_meta: &RecipeMeta, - tasks: &mut HashMap>, + tasks: &mut HashMap>>, ) -> Result<()> { let recipe = format!("{basename}/{recipename}"); let recipe_def = CURRENT_RECIPE.set(&recipe, || read_yaml::(path))?; @@ -140,8 +141,10 @@ fn read_subrecipe_tasks( Ok(()) } -pub fn read_recipes>(path: P) -> Result>> { - let mut tasks = HashMap::>::new(); +pub fn read_recipes>( + path: P, +) -> Result>>> { + let mut tasks = HashMap::>>::new(); let mut recipe_metas = HashMap::::new(); for entry in WalkDir::new(path) diff --git a/crates/rebel/src/resolve.rs b/crates/rebel/src/resolve.rs index 896903f..27a6d5c 100644 --- a/crates/rebel/src/resolve.rs +++ b/crates/rebel/src/resolve.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::fmt; use std::rc::Rc; -use rebel_common::types::TaskID; +use rebel_common::types::TaskIDRef; use crate::args::TaskArgs; use crate::context::{self, Context, OutputRef, TaskRef}; @@ -38,8 +38,8 @@ impl<'ctx> From<&TaskRef<'ctx>> for DepChain<'ctx> { } } -impl<'ctx> From<&'ctx TaskID> for DepChain<'ctx> { - fn from(id: &'ctx TaskID) -> Self { +impl<'ctx> From> for DepChain<'ctx> { + fn from(id: TaskIDRef<'ctx>) -> Self { TaskRef { id, args: Rc::new(TaskArgs::default()), -- cgit v1.2.3