-
Notifications
You must be signed in to change notification settings - Fork 4
/
Controller.cpp
81 lines (73 loc) · 2.99 KB
/
Controller.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "Controller.h"
using namespace std;
FixedController::FixedController(size_t coroutines, size_t sampling_interval) :
coroutines{ coroutines },
sampling_interval{ sampling_interval },
completed{} { }
void FixedController::register_completion(unsigned int current_coroutines) {
if (++completed < sampling_interval) return;
const auto end = chrono::system_clock::now();
const chrono::duration<double> elapsed = end - start;
const auto velocity = static_cast<double>(completed) / static_cast<double>(elapsed.count());
cout << "[ ] Request velocity: " << velocity << " rps. Recommended coros (fixed): " << coroutines << "; Current coros: " << current_coroutines << endl;
start = end;
completed = 0;
}
size_t FixedController::recommended_coroutines() const noexcept {
return coroutines;
}
AdaptiveController::AdaptiveController(size_t initial_coroutines, size_t sample_size,
size_t sample_interval, size_t minimum_coroutines, size_t maximum_coroutines) :
coroutines{sample_size},
velocities{sample_size},
start{chrono::system_clock::now()},
completed{},
sample_interval{sample_interval},
recommended{initial_coroutines},
max_coro{ maximum_coroutines },
min_coro{ minimum_coroutines } { }
void AdaptiveController::register_completion(unsigned int current_coroutines) {
if (++completed < sample_interval) return;
const auto end = chrono::system_clock::now();
const chrono::duration<double> elapsed = end - start;
velocities.push_back(static_cast<double>(completed) / static_cast<double>(elapsed.count()));
coroutines.push_back(current_coroutines);
cout << "[ ] Request velocity: " << velocities.back() << " rps. Concurrent requests: " << coroutines.back() << endl;
start = end;
completed = 0;
if (velocities.size() < 2) {
recommended++;
return; // Insufficient samples
}
// Fit regression:
const auto sum_velocity = accumulate(velocities.begin(), velocities.end(), double{ 0 });
const auto mean_velocity = static_cast<double>(sum_velocity) / static_cast<double>(velocities.size());
const auto sum_coros = accumulate(coroutines.begin(), coroutines.end(), 0);
const auto mean_coros = static_cast<double>(sum_coros) / static_cast<double>(coroutines.size());
double ss_coros{};
for (const auto coro : coroutines) {
const auto delta = coro - mean_coros;
ss_coros += delta * delta;
}
if (ss_coros < 0.0001) {
recommended++;
return; // Insufficient variation
}
double ss_covar{};
for (int i{}; i < velocities.size(); i++) {
ss_covar += (coroutines[i] - mean_coros) * (velocities[i] - mean_velocity);
}
if (ss_covar < 0.0001) {
recommended++;
return; // Insufficient variation
}
const auto beta = ss_coros / ss_covar;
if (beta > 0 && recommended < max_coro) {
recommended++;
} else if (beta < 0 && recommended > min_coro) {
recommended--;
}
}
size_t AdaptiveController::recommended_coroutines() const noexcept {
return recommended;
}