Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/2, 4, 31, 32 코드 리뷰 #34

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
992e96b
feat: add type field and change some conditions
YoonsungNam Sep 10, 2018
3479f48
Feat: Modify the pending_queue to treat more than two workloads
YoonsungNam Sep 17, 2018
702507f
fix: fix NumaTopology from async to sync
YoonsungNam Sep 18, 2018
91ce249
Merge branch 'master' into issue/2
YoonsungNam Sep 18, 2018
ee6a735
fix: Fix grouping code in pending_queue.py
YoonsungNam Sep 19, 2018
75f8bfb
feat: Add SwapIsolator skeleton code
YoonsungNam Sep 19, 2018
a09f1d4
feat: Add cgroup cycle throttle and create cgroup.py based on cgroup_…
YoonsungNam Sep 20, 2018
063e25b
feat: Fix SchedIsolator (strengthen, weaken, properties)
YoonsungNam Sep 20, 2018
9bef947
fix: Rename to CoreIsolator and add fg_next_step code
YoonsungNam Sep 21, 2018
46029a9
fix: Fix hard coded parts and add resctrl.py to utils
YoonsungNam Sep 21, 2018
40b29eb
feat: Add Swap related code
YoonsungNam Sep 21, 2018
4347308
feat: Separate fg and bg in CoreIsolator
YoonsungNam Sep 23, 2018
d559567
feat: Add ResourceType.CPU and related logics
YoonsungNam Sep 24, 2018
62858e9
fix: Change the diff policies for ResourceType.CPU
YoonsungNam Sep 24, 2018
656d692
fix: Fix fg_strengthen/weaken_cond not to exceed socket boudnary
YoonsungNam Sep 24, 2018
974f940
feat: Add swap_iso.py and related codes
YoonsungNam Sep 25, 2018
70e50e5
feat: Add SwapIsolator and related code
YoonsungNam Sep 26, 2018
fdfebd3
fix: Modify CoreIso., MemoryIso., and dvfs.py to set workload's cpufreq.
YoonsungNam Sep 27, 2018
1bc0d35
fix: fix minor typo
YoonsungNam Sep 27, 2018
766596f
feat: Add update_isolation_config func. to store setting to each class
YoonsungNam Sep 27, 2018
c251e14
fix: Add swap setting related codes
YoonsungNam Sep 29, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
import isolating_controller
from isolating_controller.isolation import NextStep
from isolating_controller.isolation.isolators import Isolator
from isolating_controller.isolation.policies import DiffPolicy, IsolationPolicy
from isolating_controller.isolation.policies import GreedyDiffWViolationPolicy, DiffCPUPolicy, DiffPolicy, IsolationPolicy
from isolating_controller.metric_container.basic_metric import BasicMetric
from isolating_controller.workload import Workload
from pending_queue import PendingQueue
from swap_iso import SwapIsolator

MIN_PYTHON = (3, 6)

Expand All @@ -44,7 +45,8 @@ def __init__(self, metric_buf_size: int) -> None:
self._rmq_host = 'localhost'
self._rmq_creation_queue = 'workload_creation'

self._pending_wl = PendingQueue(DiffPolicy)
## FIXME : Hard coded - PendingQueue can have four workloads at most (second argument)
self._pending_wl = PendingQueue(DiffCPUPolicy, 2)
self._control_thread = ControlThread(self._pending_wl)

def _cbk_wl_creation(self, ch: BlockingChannel, method: Basic.Deliver, _: BasicProperties, body: bytes) -> None:
Expand All @@ -55,23 +57,25 @@ def _cbk_wl_creation(self, ch: BlockingChannel, method: Basic.Deliver, _: BasicP
logger = logging.getLogger('monitoring.workload_creation')
logger.debug(f'{arr} is received from workload_creation queue')

if len(arr) != 4:
if len(arr) != 5:
return

wl_name, pid, perf_pid, perf_interval = arr
wl_identifier, wl_type, pid, perf_pid, perf_interval = arr
pid = int(pid)
perf_pid = int(perf_pid)
perf_interval = int(perf_interval)
item = wl_identifier.split('_')
wl_name = item[0]

if not psutil.pid_exists(pid):
return

workload = Workload(wl_name, pid, perf_pid, perf_interval)

# FIXME: hard coded
if wl_name == 'SP':
workload = Workload(wl_name, wl_type, pid, perf_pid, perf_interval)
if wl_type == 'bg':
logger.info(f'{workload} is background process')
self._pending_wl.add_bg(workload)
else:
logger.info(f'{workload} is foreground process')
self._pending_wl.add_fg(workload)

logger.info(f'{workload} is created')
Expand Down Expand Up @@ -134,12 +138,17 @@ def __init__(self, pending_queue: PendingQueue) -> None:

self._pending_queue: PendingQueue = pending_queue

self._interval: int = 2 # Scheduling interval
self._interval: float = 0.2 # Scheduling interval
self._isolation_groups: Dict[IsolationPolicy, int] = dict()
self._all_groups: Dict[int, IsolationPolicy] = dict()
self._swapper: SwapIsolator = None

def _isolate_workloads(self) -> None:
logger = logging.getLogger(__name__)

# TODO: Swapper may come here
self._swapper.try_swap()

for group, iteration_num in self._isolation_groups.items():
logger.info('')
logger.info(f'***************isolation of {group.name} #{iteration_num}***************')
Expand Down Expand Up @@ -187,6 +196,12 @@ def _register_pending_workloads(self) -> None:
self._isolation_groups[pending_group] = 0
pending_group.init_isolators()

# init self._all_groups if pending_group exist
if len(self._isolation_groups) > 0:
all_groups = list(self._isolation_groups.keys())
for idx, group in enumerate(all_groups):
self._all_groups[idx] = group

def _remove_ended_groups(self) -> None:
"""
deletes the finished workloads(threads) from the dict.
Expand All @@ -209,6 +224,8 @@ def run(self) -> None:
logger = logging.getLogger(__name__)
logger.info('starting isolation loop')

# Swapper init
self._swapper = SwapIsolator(self._all_groups)
while True:
self._remove_ended_groups()
self._register_pending_workloads()
Expand Down
7 changes: 7 additions & 0 deletions isolating_controller/isolation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ class NextStep(IntEnum):
WEAKEN = 2
STOP = 3
IDLE = 4


class ResourceType(IntEnum):
CPU = 0
CACHE = 1
MEMORY = 2
Unknown = 3
2 changes: 1 addition & 1 deletion isolating_controller/isolation/isolators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .cache import CacheIsolator
from .idle import IdleIsolator
from .memory import MemoryIsolator
from .schedule import SchedIsolator
from .core import CoreIsolator
27 changes: 21 additions & 6 deletions isolating_controller/isolation/isolators/base_isolator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

from abc import ABCMeta, abstractmethod

from .. import NextStep
from typing import Optional

from .. import NextStep, ResourceType
from ...metric_container.basic_metric import MetricDiff
from ...workload import Workload


class Isolator(metaclass=ABCMeta):
def __init__(self, foreground_wl: Workload, background_wl: Workload) -> None:
def __init__(self, foreground_wl: Workload, background_wl: Workload, cont_resource: Optional[ResourceType]) -> None:
self._prev_metric_diff: MetricDiff = foreground_wl.calc_metric_diff()

self._foreground_wl = foreground_wl
self._background_wl = background_wl

self._is_fist_decision: bool = True
self._fg_next_step = NextStep.IDLE
self._bg_next_step = NextStep.IDLE

self._is_first_decision: bool = True
self._contentious_resource: Optional[ResourceType] = cont_resource

@abstractmethod
def strengthen(self) -> 'Isolator':
Expand Down Expand Up @@ -63,7 +69,7 @@ def yield_isolation(self) -> None:
Declare to stop the configuration search for the current isolator.
Must be called when the current isolator yields the initiative.
"""
self._is_fist_decision = True
self._is_first_decision = True

@abstractmethod
def _first_decision(self) -> NextStep:
Expand All @@ -74,9 +80,18 @@ def _monitoring_result(self) -> NextStep:
pass

def decide_next_step(self) -> NextStep:
if self._is_fist_decision:
self._is_fist_decision = False
if self._is_first_decision:
self._is_first_decision = False
return self._first_decision()

else:
return self._monitoring_result()

@abstractmethod
def update_isolation_config(self) -> None:
"""
Update the isolator configuration parameters to each workloads after enforcing isolation
(E.g., Update the core frequencies after enforcing isolation)
:return:
"""
pass
84 changes: 54 additions & 30 deletions isolating_controller/isolation/isolators/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,52 @@
from typing import Optional

from .base_isolator import Isolator
from .. import NextStep
from ...utils import CAT
from .. import NextStep, ResourceType
from ...utils import ResCtrl
from ...workload import Workload


class CacheIsolator(Isolator):
_DOD_THRESHOLD = 0.005
_FORCE_THRESHOLD = 0.1

def __init__(self, foreground_wl: Workload, background_wl: Workload) -> None:
super().__init__(foreground_wl, background_wl)
def __init__(self, foreground_wl: Workload, background_wl: Workload, cont_resource: Optional[ResourceType]) -> None:
super().__init__(foreground_wl, background_wl, cont_resource)

self._prev_step: Optional[int] = None
self._cur_step: Optional[int] = None

self._fg_grp_name = f'{foreground_wl.name}_{foreground_wl.pid}'
CAT.create_group(self._fg_grp_name)
for tid in foreground_wl.all_child_tid():
CAT.add_task(self._fg_grp_name, tid)

self._bg_grp_name = f'{background_wl.name}_{background_wl.pid}'
CAT.create_group(self._bg_grp_name)
for tid in background_wl.all_child_tid():
CAT.add_task(self._bg_grp_name, tid)

self._fg_resctrl = ResCtrl(self._fg_grp_name)
self._bg_resctrl = ResCtrl(self._bg_grp_name)

# Save the CacheIsolator setting to `Workload`
foreground_wl._resctrl = self._fg_resctrl
background_wl._resctrl = self._bg_resctrl

def __del__(self) -> None:
logger = logging.getLogger(__name__)

max_bits = ResCtrl.MAX_BITS
max_mask = ResCtrl.gen_mask(0, max_bits)

if self._foreground_wl.is_running:
logger.debug(f'reset resctrl configuration of {self._foreground_wl}')
# FIXME: hard coded
CAT.assign(self._fg_grp_name, '1', CAT.gen_mask(0, CAT.MAX))
# FIXME: The number of socket is two at most
ResCtrl.assign_llc(self._fg_resctrl, max_mask, max_mask)

if self._background_wl.is_running:
logger.debug(f'reset resctrl configuration of {self._background_wl}')
# FIXME: hard coded
CAT.assign(self._bg_grp_name, '1', CAT.gen_mask(0, CAT.MAX))
# FIXME: The number of socket is two at most
ResCtrl.assign_llc(self._bg_resctrl, max_mask, max_mask)

def strengthen(self) -> 'CacheIsolator':
self._prev_step = self._cur_step

if self._cur_step is None:
self._cur_step = CAT.MAX // 2
self._cur_step = ResCtrl.MAX_BITS // 2
else:
self._cur_step += 1

Expand All @@ -66,34 +69,51 @@ def weaken(self) -> 'CacheIsolator':
@property
def is_max_level(self) -> bool:
# FIXME: hard coded
return self._cur_step is not None and self._cur_step + CAT.STEP >= CAT.MAX
return self._cur_step is not None and self._cur_step + ResCtrl.STEP >= ResCtrl.MAX_BITS

@property
def is_min_level(self) -> bool:
# FIXME: hard coded
return self._cur_step is None or self._cur_step - CAT.STEP <= CAT.MIN
return self._cur_step is None or self._cur_step - ResCtrl.STEP <= ResCtrl.MIN_BITS

def _enforce(self) -> None:
logger = logging.getLogger(__name__)

bg_socket_id = self._background_wl.socket_id
fg_socket_id = self._foreground_wl.socket_id

if self._cur_step is None:
logger.info('CAT off')

# FIXME: hard coded
mask = CAT.gen_mask(0, CAT.MAX)
CAT.assign(self._fg_grp_name, '1', mask)
CAT.assign(self._bg_grp_name, '1', mask)
# FIXME: The number of socket is two at most
mask = ResCtrl.gen_mask(0, ResCtrl.MAX_BITS)
if bg_socket_id == 0:
ResCtrl.assign_llc(self._bg_resctrl, mask, '1')
if bg_socket_id == 1:
ResCtrl.assign_llc(self._bg_resctrl, '1', mask)
if fg_socket_id == 0:
ResCtrl.assign_llc(self._fg_resctrl, mask, '1')
if fg_socket_id == 1:
ResCtrl.assign_llc(self._fg_resctrl, '1', mask)

else:
logger.info(f'foreground : background = {self._cur_step} : {CAT.MAX - self._cur_step}')
logger.info(f'foreground : background = {self._cur_step} : {ResCtrl.MAX_BITS - self._cur_step}')

# FIXME: The number of socket is two at most
fg_mask = ResCtrl.gen_mask(0, self._cur_step)
if fg_socket_id == 0:
ResCtrl.assign_llc(self._fg_resctrl, fg_mask, '1')
if fg_socket_id == 1:
ResCtrl.assign_llc(self._fg_resctrl, '1', fg_mask)

# FIXME: hard coded
fg_mask = CAT.gen_mask(0, self._cur_step)
CAT.assign(self._fg_grp_name, '1', fg_mask)
# FIXME: The number of socket is two at most
bg_mask = ResCtrl.gen_mask(self._cur_step)
if bg_socket_id == 0:
ResCtrl.assign_llc(self._bg_resctrl, bg_mask, '1')
if bg_socket_id == 1:
ResCtrl.assign_llc(self._bg_resctrl, '1', bg_mask)

# FIXME: hard coded
bg_mask = CAT.gen_mask(self._cur_step)
CAT.assign(self._bg_grp_name, '1', bg_mask)
self.update_isolation_config()

def _first_decision(self) -> NextStep:
metric_diff = self._foreground_wl.calc_metric_diff()
Expand Down Expand Up @@ -128,7 +148,7 @@ def _monitoring_result(self) -> NextStep:
logger.debug(f'current diff: {curr_diff:>7.4f}, previous diff: {prev_diff:>7.4f}')

if self._cur_step is not None \
and not (CAT.MIN < self._cur_step < CAT.MAX) \
and not (ResCtrl.MIN_BITS < self._cur_step < ResCtrl.MAX_BITS) \
or abs(diff_of_diff) <= CacheIsolator._DOD_THRESHOLD \
or abs(curr_diff) <= CacheIsolator._DOD_THRESHOLD:
return NextStep.STOP
Expand All @@ -144,3 +164,7 @@ def _monitoring_result(self) -> NextStep:
return NextStep.STOP
else:
return NextStep.STRENGTHEN

def update_isolation_config(self) -> None:
self._foreground_wl._resctrl = self._fg_resctrl
self._background_wl._resctrl = self._bg_resctrl
Loading