From: Dominik Rusovac <d.rusovac@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [RFC proxmox 1/3] resource-scheduling: add lab feature
Date: Fri, 6 Mar 2026 09:20:44 +0100 [thread overview]
Message-ID: <20260306082046.34311-2-d.rusovac@proxmox.com> (raw)
In-Reply-To: <20260306082046.34311-1-d.rusovac@proxmox.com>
Add feature-gated modules to evaluate several statically
dispatched variants of TOPSIS-based static resource scheduling.
The 'lab' feature ought to be activated during tests that involve
variants of TOPSIS-based static resource scheduling.
Signed-off-by: Dominik Rusovac <d.rusovac@proxmox.com>
---
proxmox-resource-scheduling/Cargo.toml | 3 ++
proxmox-resource-scheduling/src/pve_static.rs | 44 +++++++++++++++++
proxmox-resource-scheduling/src/topsis.rs | 48 +++++++++++++++++++
3 files changed, 95 insertions(+)
diff --git a/proxmox-resource-scheduling/Cargo.toml b/proxmox-resource-scheduling/Cargo.toml
index a73d8884..5060fae3 100644
--- a/proxmox-resource-scheduling/Cargo.toml
+++ b/proxmox-resource-scheduling/Cargo.toml
@@ -11,3 +11,6 @@ exclude.workspace = true
[dependencies]
anyhow.workspace = true
serde = { workspace = true, features = [ "derive" ] }
+
+[features]
+lab = []
diff --git a/proxmox-resource-scheduling/src/pve_static.rs b/proxmox-resource-scheduling/src/pve_static.rs
index b81086dd..0afbec05 100644
--- a/proxmox-resource-scheduling/src/pve_static.rs
+++ b/proxmox-resource-scheduling/src/pve_static.rs
@@ -132,3 +132,47 @@ pub fn score_nodes_to_start_service<T: AsRef<StaticNodeUsage>>(
.map(|(n, score)| (nodes[n].as_ref().name.clone(), score))
.collect())
}
+
+#[cfg(feature = "lab")]
+pub mod evaluate {
+ use crate::{
+ pve_static::score_nodes_to_start_service,
+ topsis::evaluate::{score_alternatives_with_variant, DispatchedTopsis},
+ };
+
+ use super::{StaticNodeUsage, StaticServiceUsage, N_CRITERIA, PVE_HA_TOPSIS_CRITERIA};
+
+ /// Dispatched parts of static resource scheduling
+ pub trait DispatchedStaticResourceScheduler {
+ /// The method to turn the stats of `nodes` and `service` into alternatives
+ fn preprocess<T: AsRef<StaticNodeUsage>>(
+ &self,
+ nodes: &[T],
+ service: &StaticServiceUsage,
+ ) -> Vec<[f64; N_CRITERIA]>;
+ }
+
+ /// Score `nodes` using specific `topsis_variant` and `static_resource_scheduling_variant`.
+ ///
+ /// Calls [`crate::topsis::score_nodes_to_start_service`] if `static_resource_scheduling_variant` is [`None`]
+ pub fn score_nodes_to_start_service_with_variant<T: AsRef<StaticNodeUsage>>(
+ nodes: &[T],
+ service: &StaticServiceUsage,
+ topsis_variant: Option<&impl DispatchedTopsis<N_CRITERIA>>,
+ static_resource_scheduling_variant: Option<&impl DispatchedStaticResourceScheduler>,
+ ) -> Vec<(String, f64)> {
+ match static_resource_scheduling_variant {
+ Some(static_resource_scheduling) => score_alternatives_with_variant(
+ topsis_variant,
+ static_resource_scheduling.preprocess(nodes, service),
+ &PVE_HA_TOPSIS_CRITERIA,
+ )
+ .into_iter()
+ .enumerate()
+ .map(|(n, score)| (nodes[n].as_ref().name.clone(), score))
+ .collect(),
+ _ => score_nodes_to_start_service(nodes, service)
+ .unwrap_or_else(|err| panic!("scoring nodes to start service failed: {err}")),
+ }
+ }
+}
diff --git a/proxmox-resource-scheduling/src/topsis.rs b/proxmox-resource-scheduling/src/topsis.rs
index 6d078aa6..f52ee27d 100644
--- a/proxmox-resource-scheduling/src/topsis.rs
+++ b/proxmox-resource-scheduling/src/topsis.rs
@@ -245,3 +245,51 @@ macro_rules! criteria_struct {
}
};
}
+
+#[cfg(feature = "lab")]
+pub mod evaluate {
+ use super::{score_alternatives, Criteria, IdealAlternatives, Matrix};
+
+ /// Dispatched parts of TOPSIS algorithm
+ pub trait DispatchedTopsis<const N: usize> {
+ /// The method to normalize `alternatives`
+ fn normalize(&self, alternatives: &mut Matrix<N>);
+
+ /// The method to compute the designated distance of `alternative` to `ideals`
+ #[allow(private_interfaces)]
+ fn distance(
+ &self,
+ alternative: &[f64; N],
+ criteria: &Criteria<N>,
+ ideals: &IdealAlternatives<N>,
+ ) -> f64;
+ }
+
+ /// Score alternatives with specific dispatched `topsis_variant`.
+ ///
+ /// Calls [`crate::topsis::score_alternatives`] if `topsis_variant` is [`None`]
+ pub fn score_alternatives_with_variant<const N: usize>(
+ topsis_variant: Option<&impl DispatchedTopsis<N>>,
+ instance: Vec<[f64; N]>,
+ criteria: &Criteria<N>,
+ ) -> Vec<f64> {
+ match topsis_variant {
+ Some(topsis) => {
+ let mut alternatives = Matrix(instance);
+
+ topsis.normalize(&mut alternatives);
+
+ let ideals = IdealAlternatives::compute(&alternatives, criteria);
+
+ alternatives
+ .0
+ .iter()
+ .map(|alternative| topsis.distance(alternative, criteria, &ideals))
+ .collect()
+ }
+ _ => Matrix::new(instance)
+ .and_then(|matrix| score_alternatives(&matrix, criteria))
+ .unwrap_or_else(|err| panic!("scoring alternatives failed: {err}")),
+ }
+ }
+}
--
2.47.3
next prev parent reply other threads:[~2026-03-06 8:20 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-06 8:20 [RFC proxmox 0/3] evaluate static scheduler variants Dominik Rusovac
2026-03-06 8:20 ` Dominik Rusovac [this message]
2026-03-06 8:20 ` [RFC proxmox 2/3] resource-scheduling: add {topsis,pve_static}-variants with basic proptests Dominik Rusovac
2026-03-06 8:20 ` [RFC proxmox 3/3] resource-scheduling: evaluate static scheduler variants Dominik Rusovac
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260306082046.34311-2-d.rusovac@proxmox.com \
--to=d.rusovac@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox