summaryrefslogtreecommitdiff
path: root/src/energy.rs
diff options
context:
space:
mode:
authorLennard Kittner <lennard@kittner.dev>2025-03-09 16:58:04 +0100
committerLennard Kittner <lennard@kittner.dev>2025-03-09 16:58:04 +0100
commite424488fd998ae442bcd34bfb5358342ad76ce99 (patch)
treec4247cad09086fbc51144e16e43c2e0c70dd77b6 /src/energy.rs
parent9ceb02c0f886a10fe8a620ad879512fa6639f6f6 (diff)
Use rapl package energy to calculate new budgets
Diffstat (limited to 'src/energy.rs')
-rw-r--r--src/energy.rs44
1 files changed, 39 insertions, 5 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)
}