summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/energy.rs44
-rw-r--r--src/energy/budget.rs15
-rw-r--r--src/energy/rapl.rs10
-rw-r--r--src/scheduler.rs2
4 files changed, 59 insertions, 12 deletions
diff --git a/src/energy.rs b/src/energy.rs
index c6cb84b..64ec267 100644
--- a/src/energy.rs
+++ b/src/energy.rs
@@ -11,7 +11,10 @@ use crate::Pid;
use anyhow::Result;
use dashmap::DashMap;
+use crate::energy::rapl::PackageEnergy;
pub use budget::BudgetPolicy;
+use perf_event::events::Event;
+use perf_event::{Builder, Counter};
pub use trackers::{Estimator, KernelDriver, MockEstimator, PerfEstimator};
pub enum Request {
@@ -27,12 +30,14 @@ pub struct ProcessInfo {
pub struct EnergyService {
estimator: Box<dyn Estimator>,
- budget_policy: Box<dyn BudgetPolicy>,
+ budget_policy: Option<Box<dyn BudgetPolicy>>,
active_processes: BTreeSet<Pid>,
process_info: HashMap<Pid, ProcessInfo>,
shared_budgets: Arc<DashMap<Pid, u64>>,
request_receiver: mpsc::Receiver<Request>,
update_interval: Duration,
+ package_energy: PackageEnergy,
+ package_energy_counter: Counter,
}
impl EnergyService {
@@ -42,15 +47,19 @@ impl EnergyService {
shared_budgets: Arc<DashMap<Pid, u64>>,
request_receiver: mpsc::Receiver<Request>,
update_interval: Duration,
+ package_energy: PackageEnergy,
+ package_energy_counter: Counter,
) -> Self {
Self {
estimator,
- budget_policy,
+ budget_policy: Some(budget_policy),
active_processes: BTreeSet::new(),
process_info: HashMap::new(),
shared_budgets,
request_receiver,
update_interval,
+ package_energy,
+ package_energy_counter,
}
}
@@ -115,7 +124,10 @@ impl EnergyService {
}
fn update_budgets(&mut self) {
- let budgets = self.budget_policy.calculate_budgets(self);
+ // We can't call self.budget_policy.calculate_budgets(self) directly because the first self borrows immutable and the self second borrows mutable
+ let policy = self.budget_policy.take().unwrap();
+ let budgets = policy.calculate_budgets(self);
+ self.budget_policy = Some(policy);
// Update the shared budgets map
for (pid, budget) in budgets {
@@ -130,6 +142,11 @@ impl EnergyService {
&self.active_processes
}
+ fn package_energy(&mut self) -> f64 {
+ self.package_energy
+ .to_joules(self.package_energy_counter.read().unwrap_or(0))
+ }
+
pub fn process_energy(&self, pid: Pid) -> Option<u64> {
self.process_info.get(&pid).map(|info| info.energy)
}
@@ -146,7 +163,7 @@ pub fn start_energy_service(
use_mocking: bool,
power_cap: u64,
shared_budgets: Arc<DashMap<Pid, u64>>,
-) -> mpsc::SyncSender<Request> {
+) -> std::io::Result<mpsc::SyncSender<Request>> {
// Potentially convert back to bounded channel
let (request_sender, request_receiver) = mpsc::sync_channel(10000);
@@ -160,6 +177,21 @@ pub fn start_energy_service(
// Create budget policy
let budget_policy = Box::new(budget::SimpleCappingPolicy::new(power_cap));
+ // shouldn't be a problem because we are privileged
+ // if PackageEnergy::check_paranoid().unwrap_or(3) > 0 {}
+
+ let package_energy = PackageEnergy::new().unwrap();
+
+ // Any cpu should be fine because the package power should be the same for every cpu
+ let mut package_energy_counter = Builder::new()
+ .kind(Event::Raw(
+ package_energy.get_type(),
+ package_energy.get_event_config(),
+ ))
+ .any_cpu()
+ .build()?;
+ package_energy_counter.enable()?;
+
// Create and start the energy service
let service = EnergyService::new(
estimator,
@@ -167,9 +199,11 @@ pub fn start_energy_service(
shared_budgets,
request_receiver,
Duration::from_millis(50), // 50ms update interval
+ package_energy,
+ package_energy_counter,
);
service.run();
- request_sender
+ Ok(request_sender)
}
diff --git a/src/energy/budget.rs b/src/energy/budget.rs
index aada2eb..7a2c7e2 100644
--- a/src/energy/budget.rs
+++ b/src/energy/budget.rs
@@ -5,7 +5,7 @@ use crate::energy::EnergyService;
type Pid = i32;
pub trait BudgetPolicy: Send + 'static {
- fn calculate_budgets(&self, energy_service: &EnergyService) -> HashMap<Pid, u64>;
+ fn calculate_budgets(&self, energy_service: &mut EnergyService) -> HashMap<Pid, u64>;
}
pub struct SimpleCappingPolicy {
@@ -19,21 +19,24 @@ impl SimpleCappingPolicy {
}
impl BudgetPolicy for SimpleCappingPolicy {
- fn calculate_budgets(&self, energy_service: &EnergyService) -> HashMap<Pid, u64> {
+ fn calculate_budgets(&self, energy_service: &mut EnergyService) -> HashMap<Pid, u64> {
let mut budgets = HashMap::new();
let process_energies = energy_service.all_process_energies();
// Total energy consumption across all processes
- let total_energy: u64 = process_energies.values().sum();
+ //let total_energy: u64 = process_energies.values().sum();
+
+ let actual_energy =
+ energy_service.package_energy() / energy_service.update_interval.as_secs_f64();
// Simple proportional distribution if over cap
- if total_energy > self.power_cap {
- let ratio = self.power_cap as f64 / total_energy as f64;
+ if actual_energy > self.power_cap as f64 {
+ let ratio = self.power_cap as f64 / actual_energy as f64;
for (&pid, &energy) in &process_energies {
// Calculate a scaled budget based on the ratio
// Higher energy consumers get proportionally reduced budgets
- let scaling_factor = 1.0 - ((energy as f64 / total_energy as f64) * (1.0 - ratio));
+ let scaling_factor = 1.0 - ((energy as f64 / actual_energy) * (1.0 - ratio));
let budget = (u64::MAX as f64 * scaling_factor) as u64;
budgets.insert(pid, budget);
}
diff --git a/src/energy/rapl.rs b/src/energy/rapl.rs
index 293a0f7..34b128e 100644
--- a/src/energy/rapl.rs
+++ b/src/energy/rapl.rs
@@ -76,6 +76,16 @@ impl PackageEnergy {
raw_value as f64 * self.scale
}
+ /// Get the perf event type
+ pub fn get_type(&self) -> u32 {
+ self.event_type
+ }
+
+ /// Get the event config
+ pub fn get_event_config(&self) -> u64 {
+ self.event_config
+ }
+
/// Check if perf_event_paranoid setting might cause permission issues
pub fn check_paranoid() -> io::Result<i32> {
let path = Path::new("/proc/sys/kernel/perf_event_paranoid");
diff --git a/src/scheduler.rs b/src/scheduler.rs
index 8618b78..0cc9522 100644
--- a/src/scheduler.rs
+++ b/src/scheduler.rs
@@ -56,7 +56,7 @@ impl<'a> Scheduler<'a> {
// Start energy tracking service
let energy_sender =
- energy::start_energy_service(use_mocking, power_cap, shared_budgets.clone());
+ energy::start_energy_service(use_mocking, power_cap, shared_budgets.clone())?;
let topology = Topology::new().unwrap();
let mut e_core_ids = Vec::new();