response_time_analysis/wcet/
curve.rs1use std::cell::RefCell;
2use std::collections::VecDeque;
3use std::iter::FromIterator;
4use std::rc::Rc;
5
6use super::JobCostModel;
7use crate::time::Service;
8
9#[derive(Clone, Debug)]
14pub struct Curve {
15 wcet_of_n_jobs: Vec<Service>,
16}
17
18impl Curve {
19 pub fn new(wcet_of_n_jobs: Vec<Service>) -> Self {
33 Curve { wcet_of_n_jobs }
34 }
35}
36
37impl JobCostModel for Curve {
38 fn cost_of_jobs(&self, n: usize) -> Service {
39 if !self.wcet_of_n_jobs.is_empty() && n > 0 {
40 let x = n / self.wcet_of_n_jobs.len();
42 let y = n % self.wcet_of_n_jobs.len();
43 let prefix = if x > 0 {
44 self.wcet_of_n_jobs[self.wcet_of_n_jobs.len() - 1] * x as u64
45 } else {
46 Service::none()
47 };
48 let suffix = if y > 0 {
49 self.wcet_of_n_jobs[y - 1]
51 } else {
52 Service::none()
53 };
54 prefix + suffix
55 } else {
56 Service::none()
57 }
58 }
59
60 fn job_cost_iter<'a>(&'a self) -> Box<dyn Iterator<Item = Service> + 'a> {
61 Box::new((1..).map(move |n| self.cost_of_jobs(n) - self.cost_of_jobs(n - 1)))
62 }
63
64 fn least_wcet(&self, n: usize) -> Service {
65 if n > 0 {
66 let mut least = self.wcet_of_n_jobs[0];
67 for i in 1..self.wcet_of_n_jobs.len().min(n) {
68 least = least.min(self.wcet_of_n_jobs[i] - self.wcet_of_n_jobs[i - 1])
69 }
70 least
71 } else {
72 Service::none()
73 }
74 }
75}
76
77impl Curve {
78 pub fn from_trace(job_costs: impl Iterator<Item = Service>, max_n: usize) -> Curve {
79 let mut cost_of = Vec::with_capacity(max_n);
80 let mut window: VecDeque<Service> = VecDeque::with_capacity(max_n + 1);
81
82 for c in job_costs {
84 window.push_back(c);
86 if window.len() > max_n {
88 window.pop_front();
89 }
90
91 let mut total_cost = Service::none();
93 for (i, k) in window.iter().enumerate() {
94 total_cost += *k;
95 if cost_of.len() <= i {
96 cost_of.push(total_cost)
98 } else {
99 cost_of[i] = cost_of[i].max(total_cost)
101 }
102 }
103 }
104
105 Curve {
106 wcet_of_n_jobs: cost_of,
107 }
108 }
109
110 fn extrapolate_next(&self) -> Service {
111 let n = self.wcet_of_n_jobs.len();
112 assert!(n >= 2);
113 (0..=(n / 2))
116 .map(|k| self.wcet_of_n_jobs[k] + self.wcet_of_n_jobs[n - k - 1])
117 .min()
118 .unwrap()
119 }
120
121 pub fn extrapolate(&mut self, n: usize) {
122 if self.wcet_of_n_jobs.len() >= 3 {
124 while self.wcet_of_n_jobs.len() < n - 1 {
125 self.wcet_of_n_jobs.push(self.extrapolate_next())
126 }
127 }
128 }
129}
130
131impl FromIterator<Service> for Curve {
132 fn from_iter<I: IntoIterator<Item = Service>>(iter: I) -> Curve {
133 let mut wcets: Vec<Service> = iter.into_iter().collect();
134 for i in 1..wcets.len() {
136 wcets[i] = wcets[i].max(wcets[i - 1]);
137 }
138 Curve::new(wcets)
139 }
140}
141
142#[derive(Clone, Debug)]
146pub struct ExtrapolatingCurve {
147 prefix: Rc<RefCell<Curve>>,
148}
149
150impl ExtrapolatingCurve {
151 pub fn new(costfn: Curve) -> Self {
152 ExtrapolatingCurve {
153 prefix: Rc::new(RefCell::new(costfn)),
154 }
155 }
156}
157
158impl JobCostModel for ExtrapolatingCurve {
159 fn cost_of_jobs(&self, n: usize) -> Service {
160 let mut costfn = self.prefix.borrow_mut();
161 costfn.extrapolate(n + 1);
162 costfn.cost_of_jobs(n)
163 }
164
165 fn job_cost_iter<'a>(&'a self) -> Box<dyn Iterator<Item = Service> + 'a> {
166 Box::new((1..).map(move |n| self.cost_of_jobs(n) - self.cost_of_jobs(n - 1)))
167 }
168
169 fn least_wcet(&self, n: usize) -> Service {
170 self.prefix.borrow().least_wcet(n)
173 }
174}