-
Notifications
You must be signed in to change notification settings - Fork 1
/
simple.py
167 lines (108 loc) · 4.35 KB
/
simple.py
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from __future__ import division
from Constants import *
import random
import math
"""
A simulation scenario where the percentage of reads varies periodically from 50% to 100%
and the capacity of each VM is proportional to that percentage.
"""
class ReadLoadScenario(object):
def __init__(self, training_steps, testing_steps, load_period=250, init_vms=10, min_vms=1, max_vms=20):
self.time = 0
self.load_period = load_period
self.training_steps = training_steps
self.testing_steps = testing_steps
self.MIN_VMS = min_vms
self.MAX_VMS = max_vms
self.measurements = self._get_measurements(init_vms)
"""
Returns the measurements for the current state of the system
"""
def get_current_measurements(self):
return dict(self.measurements)
"""
Executes the given action, updating the current measurements accordingly
"""
def execute_action(self, action):
self.time += 1
num_vms = self.measurements[NUMBER_OF_VMS]
# action_type, action_value = action
# if action_type == ADD_VMS:
# num_vms += action_value
# if action_type == REMOVE_VMS:
# num_vms -= action_value
if action[0] == 0:
num_vms += 1
elif action[0] == 1:
num_vms -= 1
if num_vms < self.MIN_VMS:
num_vms = self.MIN_VMS
if num_vms > self.MAX_VMS:
num_vms = self.MAX_VMS
self.measurements = self._get_measurements(num_vms)
reward = self._get_reward(action)
return reward
"""
Returns the reward gained by executing the given action under the current measurements
"""
def _get_reward(self, action):
vms = self.measurements[NUMBER_OF_VMS]
load = self.measurements[TOTAL_LOAD]
capacity = self.get_current_capacity()
served_load = min(capacity, load)
reward = served_load - 3 * vms
return reward
"""
Returns the current throughput capacity of the cluster
"""
def get_current_capacity(self):
vms = self.measurements[NUMBER_OF_VMS]
read_load = self.measurements[PC_READ_LOAD]
capacity = read_load * 10 * vms
return capacity
"""
Returns the measurements for the given number of vms and time
"""
def _get_measurements(self, num_vms):
measurements = {
NUMBER_OF_VMS : num_vms,
RAM_SIZE : self._get_ram_size(),
NUMBER_OF_CPUS : self._get_num_cpus(),
STORAGE_CAPACITY : self._get_storage_capacity(),
PC_FREE_RAM : self._get_free_ram(),
PC_CPU_USAGE : self._get_cpu_usage(),
IO_PER_SEC : self._get_io_per_sec(),
TOTAL_LOAD : self._get_load(),
PC_READ_LOAD : self._get_read_load(),
TOTAL_LATENCY : self._get_latency()
}
return measurements
"""
Methods that return the current values for each of the parameters
"""
def _get_load(self):
# double the frequency during the testing period
if self.time <= self.training_steps:
return 50.0 + 50 * math.sin(2 * math.pi * self.time / self.load_period)
elif self.time <= self.training_steps + self.testing_steps:
return 50.0 + 50 * math.sin(2 * math.pi * (self.time-self.training_steps) * 2 / self.load_period)
def _get_read_load(self):
# double the frequency during the testing period
if self.time <= self.training_steps:
return 0.75 + 0.25 * math.sin(2 * math.pi * self.time / 340)
elif self.time <= self.training_steps + self.testing_steps:
return 0.75 + 0.25 * math.sin(2 * math.pi * (self.time-self.training_steps) / 340)
def _get_latency(self):
return 0.5 + 0.5 * random.uniform(0, 1)
def _get_free_ram(self):
return 0.4 + 0.4 * random.uniform(0, 1)
def _get_cpu_usage(self):
return 0.6 + 0.3 * random.uniform(0, 1)
def _get_io_per_sec(self):
return 1000 + 800 * random.uniform(0, 1)
def _get_storage_capacity(self):
return random.choice([10, 20])
def _get_num_cpus(self):
return random.choice([2, 4])
def _get_ram_size(self):
return random.choice([1024, 2048])