Skip to content

Commit

Permalink
Results: added Scalar samples/results support
Browse files Browse the repository at this point in the history
The only way to saving scalar samples/results is
to use PerfInterval and {Sequential,Parallel}PerfResult.
However, these are meant to store vector/multidimensional
data - value and duration and all the calculations
it does expects vector data.
  • Loading branch information
enhaut committed Sep 16, 2024
1 parent 87ce8f5 commit 216f876
Showing 1 changed file with 55 additions and 3 deletions.
58 changes: 55 additions & 3 deletions lnst/RecipeCommon/Perf/Results.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,43 @@ def end_timestamp(self):
def time_slice(self, start, end):
raise NotImplementedError()

class ScalarSample(PerfResult):
def __init__(self, value, unit, timestamp):
self._value = value
self._unit = unit
self._timestamp = timestamp

@property
def value(self):
return self._value

@property
def duration(self):
return 1 # just to make it compatible with other PerfInterval objects

@property
def unit(self):
return self._unit

@property
def start_timestamp(self):
return self._timestamp

@property
def end_timestamp(self):
return self._timestamp

def time_slice(self, start, end):
if end <= self.start_timestamp or start >= self.end_timestamp:
raise EmptySlice(
"current start, end {} {}; request start, end {}, {}".format(
self.start_timestamp, self.end_timestamp, start, end,
)
)

return ScalarSample(self.value, self.unit, self.start_timestamp)


class PerfInterval(PerfResult):
def __init__(self, value, duration, unit, timestamp):
self._value = value
Expand Down Expand Up @@ -110,7 +147,8 @@ def _validate_item(self, item):

def _validate_item_type(self, item):
if (not isinstance(item, PerfInterval) and
not isinstance(item, PerfList)):
not isinstance(item, PerfList) and
not isinstance(item, ScalarSample)):
raise LnstError("{} only accepts PerfInterval or PerfList objects."
.format(self.__class__.__name__))

Expand Down Expand Up @@ -165,7 +203,7 @@ def merge_with(self, iterable):
if type(val1) != type(val2):
raise LnstError("Cannot merge different types of PerfList objects.")

if isinstance(val1[0], PerfInterval):
if isinstance(val1[0], PerfInterval) or isinstance(val1[0], ScalarSample):
container = val1.__class__()
container.extend(val1)
container.extend(val2)
Expand Down Expand Up @@ -201,7 +239,7 @@ def samples_slice(self, slicer: callable):
if len(self) == 0:
raise EmptySlice("No samples to slice.")

if isinstance(self[0], PerfInterval):
if isinstance(self[0], PerfInterval) or isinstance(self[0], ScalarSample):
result.extend(self[slicer])
elif isinstance(self[0], PerfList):
for item in self:
Expand Down Expand Up @@ -234,6 +272,11 @@ def start_timestamp(self):
def end_timestamp(self):
return self[-1].end_timestamp


class SequentialScalarResult(SequentialPerfResult):
pass


class ParallelPerfResult(PerfList, PerfResult):
@property
def value(self):
Expand All @@ -260,6 +303,15 @@ def start_timestamp(self):
def end_timestamp(self):
return max([i.end_timestamp for i in self])


class ParallelScalarResult(ParallelPerfResult):
@property
def average(self):
samples_count = sum([len(i) for i in self])

return self.value / samples_count


def result_averages_difference(a, b):
if a is None or b is None:
return None
Expand Down

0 comments on commit 216f876

Please sign in to comment.