Skip to content

Commit

Permalink
feat: stacked bar worst-in-input and all (#339)
Browse files Browse the repository at this point in the history
* feat: stacked bar worst-in-input

Signed-off-by: rokamu623 <[email protected]>

* feat: stacked bar all

Signed-off-by: rokamu623 <[email protected]>

* fix: flake8

Signed-off-by: rokamu623 <[email protected]>

* feat: test all stacked bar

Signed-off-by: rokamu623 <[email protected]>

* feat: test worst-in-input stacked bar

Signed-off-by: rokamu623 <[email protected]>

* fix: refactor

Signed-off-by: rokamu623 <[email protected]>

* fix: spell

Signed-off-by: rokamu623 <[email protected]>

* fix: pass mypy

Signed-off-by: rokamu623 <[email protected]>

* fix: spell error

Signed-off-by: rokamu623 <[email protected]>

---------

Signed-off-by: rokamu623 <[email protected]>
  • Loading branch information
rokamu623 authored Sep 15, 2023
1 parent 049ec02 commit db4bcf3
Show file tree
Hide file tree
Showing 3 changed files with 275 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/caret_analyze/plot/stacked_bar/latency_stacked_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ def _get_response_time_record(
# include timestamp of response time (best, worst)
if self._case == 'best':
return response_time.to_best_case_stacked_bar()
if self._case == 'worst-in-input':
return response_time.to_worst_in_input_case_stacked_bar()
if self._case == 'all':
return response_time.to_all_stacked_bar()

return response_time.to_stacked_bar()

Expand Down
115 changes: 115 additions & 0 deletions src/caret_analyze/record/records_service/response_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,15 @@ def __init__(
if columns:
self._start_column = columns[0]
self._end_column = columns[-1]
self._columns = columns
else:
self._start_column = records.columns[0]
self._end_column = records.columns[-1]
self._columns = records.columns

self._start_timestamps: list[int] = []
self._end_timestamps: list[int] = []
self._records: list[RecordInterface] = []

for record in reversed(records.data):
if self._end_column in record.columns:
Expand All @@ -257,10 +260,12 @@ def __init__(
if start_ts not in self._start_timestamps:
self._start_timestamps.insert(0, start_ts)
self._end_timestamps.insert(0, end_ts)
self._records.insert(0, record)
else:
idx = self._start_timestamps.index(start_ts)
if end_ts < self._end_timestamps[idx]:
self._end_timestamps[idx] = end_ts
self._records[idx] = record

def to_all_records(self) -> RecordsInterface:
records = self._create_empty_records()
Expand Down Expand Up @@ -296,6 +301,80 @@ def to_worst_in_input_records(self) -> RecordsInterface:

return records

def to_all_stacked_bar(self) -> RecordsInterface:
end_column_record_dict: dict[int, list[RecordInterface]] = {}

# classify records which have same end timestamp
end_ts = None
for record in reversed(self._records):
if self._end_column in record.columns:
end_ts = record.get(self._end_column)
elif end_ts is None:
continue

if end_ts in end_column_record_dict.keys():
end_column_record_dict[end_ts].insert(0, record)
else:
end_column_record_dict[end_ts] = [record]

# fill empty data
filled_records_dict: dict[int, list[RecordInterface]] = {}
# for each records which have same end timestamp
for end_ts, record_list in end_column_record_dict.items():
filled_records_dict[end_ts] = []

for record in reversed(record_list):
# if record doesn't have some timestamps,
# record timestamps just after
for column in self._columns:
if column in record.columns:
continue
timestamps = [record.get(column) for record in filled_records_dict[end_ts]
if column in record.columns]
record.add(column, min(timestamps))
filled_records_dict[end_ts].append(record)

columns = [ColumnValue(c) for c in self._columns]
stacked_bar_records: RecordsInterface =\
RecordsFactory.create_instance(init=[_.data for _
in sum(filled_records_dict.values(), [])],
columns=columns)
stacked_bar_records.sort_column_order()
return stacked_bar_records

def to_worst_in_input_case_stacked_bar(self) -> RecordsInterface:
end_column_record_dict: dict[int, list[RecordInterface]] = {}

# classify records which have same end timestamp
end_ts = None
for record in reversed(self._records):
if self._end_column in record.columns:
end_ts = record.get(self._end_column)
elif end_ts is None:
continue

if end_ts in end_column_record_dict.keys():
end_column_record_dict[end_ts].append(record)
else:
end_column_record_dict[end_ts] = [record]

# generate worst-case work flow
filled_record_list: list[RecordInterface] = []
for record_list in end_column_record_dict.values():
worst_in_input_record = RecordFactory.create_instance()

for column in self._columns:
timestamps = [r.get(column) for r in record_list if column in r.columns]
worst_in_input_record.add(column, min(timestamps))
filled_record_list.append(worst_in_input_record)

columns = [ColumnValue(c) for c in self._columns]
stacked_bar_records: RecordsInterface =\
RecordsFactory.create_instance(init=[_.data for _ in filled_record_list],
columns=columns)
stacked_bar_records.sort_column_order()
return stacked_bar_records

def _create_empty_records(
self
) -> RecordsInterface:
Expand Down Expand Up @@ -413,6 +492,42 @@ def to_best_case_stacked_bar(self) -> RecordsInterface:
"""
return self._records.to_range_records('best')

def to_all_stacked_bar(self) -> RecordsInterface:
"""
Calculate records for stacked bar.
Returns
-------
RecordsInterface
Records of the all response time.
Columns
- {columns[0]}
- {columns[1]}
- {...}
- {columns[n-1]}
"""
return self._response_map_all.to_all_stacked_bar()

def to_worst_in_input_case_stacked_bar(self) -> RecordsInterface:
"""
Calculate records for stacked bar.
Returns
-------
RecordsInterface
Records of the worst-in-input cases response time.
Columns
- {columns[0]}
- {columns[1]}
- {...}
- {columns[n-1]}
"""
return self._response_map_all.to_worst_in_input_case_stacked_bar()

def to_worst_case_stacked_bar(self) -> RecordsInterface:
# NOTE:
# We think this function is unnecessary.
Expand Down
156 changes: 156 additions & 0 deletions src/test/record/records_service/test_response_time_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,159 @@ def test_drop_case(self):
]
result = to_dict(response_time.to_all_records())
assert result == expect_raw


class TestAllStackedBar:

@property
def columns(self) -> list[ColumnValue]:
return [ColumnValue('start'), ColumnValue('middle0'),
ColumnValue('middle1'), ColumnValue('end')]

@property
def column_names(self) -> list[str]:
return ['start', 'middle0', 'middle1', 'end']

def test_empty_case(self):
records_raw = []
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = []
result = to_dict(response_time.to_all_stacked_bar())
assert result == expect_raw

def test_single_case(self):
records_raw = [
{'start': 0, 'middle0': 1, 'middle1': 2, 'end': 3},
{'start': 4, 'middle0': 5, 'middle1': 7, 'end': 8},
{'start': 6, 'middle0': 7, 'middle1': 8, 'end': 9}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 2, 'end': 3},
{'start': 4, 'middle0': 5, 'middle1': 7, 'end': 8},
{'start': 6, 'middle0': 7, 'middle1': 8, 'end': 9}
]
result = to_dict(response_time.to_all_stacked_bar())
assert result == expect_raw

def test_multi_case(self):
records_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 5, 'end': 6},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 5, 'end': 6},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
result = to_dict(response_time.to_all_stacked_bar())
assert result == expect_raw

def test_drop_case(self):
records_raw = [
{'start': 0, 'middle0': 1},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 4},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 4, 'end': 6},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
result = to_dict(response_time.to_all_stacked_bar())
assert result == expect_raw


class TestWorstInInputStackedBar:

@property
def columns(self) -> list[ColumnValue]:
return [ColumnValue('start'), ColumnValue('middle0'),
ColumnValue('middle1'), ColumnValue('end')]

@property
def column_names(self) -> list[str]:
return ['start', 'middle0', 'middle1', 'end']

def test_empty_case(self):
records_raw = []
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = []
result = to_dict(response_time.to_worst_in_input_case_stacked_bar())
assert result == expect_raw

def test_single_case(self):
records_raw = [
{'start': 0, 'middle0': 1, 'middle1': 2, 'end': 3},
{'start': 4, 'middle0': 5, 'middle1': 7, 'end': 8},
{'start': 6, 'middle0': 7, 'middle1': 8, 'end': 9}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 2, 'end': 3},
{'start': 4, 'middle0': 5, 'middle1': 7, 'end': 8},
{'start': 6, 'middle0': 7, 'middle1': 8, 'end': 9}
]
result = to_dict(response_time.to_worst_in_input_case_stacked_bar())
assert result == expect_raw

def test_multi_case(self):
records_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 5, 'end': 6},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 5, 'end': 6},
]
result = to_dict(response_time.to_worst_in_input_case_stacked_bar())
assert result == expect_raw

def test_drop_case(self):
records_raw = [
{'start': 0, 'middle0': 1},
{'start': 1, 'middle0': 2, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 4},
{'start': 3, 'middle0': 4, 'middle1': 5, 'end': 6}
]
records = create_records(records_raw, self.columns)

response_time = ResponseTime(records, columns=self.column_names)

expect_raw = [
{'start': 0, 'middle0': 1, 'middle1': 3, 'end': 4},
{'start': 2, 'middle0': 3, 'middle1': 4, 'end': 6},
]
result = to_dict(response_time.to_worst_in_input_case_stacked_bar())
assert result == expect_raw

0 comments on commit db4bcf3

Please sign in to comment.