[StreamingAlgorithms] result() returns None if data is missing

Make StreamingAlgorithm.result() returning None instead of
raising RallyException in case if no (or not enough) data
has been processed.

This change was discussed at Dec' 21st on Rally weekly meeting.

Change-Id: I5c1eec47a0e190ec6ccd351b0c3bd866f4544b35
This commit is contained in:
Alexander Maretskiy 2015-12-21 19:00:24 +02:00
parent d188a5ba3b
commit 339adba2a9
4 changed files with 21 additions and 36 deletions

View File

@ -18,8 +18,6 @@ import math
import six
from rally.common.i18n import _
from rally import exceptions
from rally.task.processing import utils
@ -62,11 +60,9 @@ class MeanComputation(StreamingAlgorithm):
self.total += other.total
def result(self):
if self.count == 0:
message = _("Unable to calculate the mean: "
"no values processed so far.")
raise exceptions.RallyException(message)
return self.total / self.count
if self.count:
return self.total / self.count
return None
class StdDevComputation(StreamingAlgorithm):
@ -90,6 +86,8 @@ class StdDevComputation(StreamingAlgorithm):
self.dev_sum = self.dev_sum + (value - mean_prev) * (value - self.mean)
def merge(self, other):
if not other.mean_computation.count:
return
dev_sum1 = self.dev_sum
count1 = self.count
mean1 = self.mean
@ -107,10 +105,9 @@ class StdDevComputation(StreamingAlgorithm):
self.count * self.mean ** 2)
def result(self):
# NOTE(amaretskiy): Need at least two values to be processed
if self.count < 2:
message = _("Unable to calculate the standard deviation: "
"need at least two values to be processed.")
raise exceptions.RallyException(message)
return None
return math.sqrt(self.dev_sum / (self.count - 1))
@ -131,9 +128,6 @@ class MinComputation(StreamingAlgorithm):
self.add(other._value)
def result(self):
if self._value is None:
raise exceptions.RallyException(
_("No values have been processed"))
return self._value
@ -154,9 +148,6 @@ class MaxComputation(StreamingAlgorithm):
self.add(other._value)
def result(self):
if self._value is None:
raise exceptions.RallyException(
_("No values have been processed"))
return self._value
@ -185,10 +176,9 @@ class PercentileComputation(StreamingAlgorithm):
def result(self):
results = list(
map(lambda x: x[1], self._graph_zipper.get_zipped_graph()))
if not results:
raise exceptions.RallyException(
_("No values have been processed"))
return utils.percentile(results, self._percent)
if results:
return utils.percentile(results, self._percent)
return None
class IncrementComputation(StreamingAlgorithm):

View File

@ -44,7 +44,7 @@ class MaxAverageDuration(sla.SLA):
def merge(self, other):
self.avg_comp.merge(other.avg_comp)
self.avg = self.avg_comp.result()
self.avg = self.avg_comp.result() or 0.0
self.success = self.avg <= self.criterion_value
return self.success

View File

@ -21,7 +21,6 @@ import six
from rally.common import costilius
from rally.common import streaming_algorithms as streaming
from rally import exceptions
from rally.task.processing import utils
@ -324,10 +323,7 @@ class MainStatsTable(Chart):
for i in range(len(self.table)):
row = [self.table[i][0][1]]
# no results if all iterations failed
try:
no_result = self.table[i][-2][1].result() == 0.0
except exceptions.RallyException:
no_result = True
no_result = not self.table[i][-2][1].result()
row.extend(x[2](x[1], no_result) for x in self.table[i][1:])
rows.append(row)

View File

@ -19,7 +19,6 @@ import ddt
import six
from rally.common import streaming_algorithms as algo
from rally import exceptions
from tests.unit import test
@ -27,7 +26,7 @@ class MeanComputationTestCase(test.TestCase):
def test_empty_stream(self):
mean_computation = algo.MeanComputation()
self.assertRaises(exceptions.RallyException, mean_computation.result)
self.assertIsNone(mean_computation.result())
def test_one_value(self):
mean_computation = algo.MeanComputation()
@ -68,12 +67,12 @@ class StdDevComputationTestCase(test.TestCase):
def test_empty_stream(self):
std_computation = algo.StdDevComputation()
self.assertRaises(exceptions.RallyException, std_computation.result)
self.assertIsNone(std_computation.result())
def test_one_value(self):
std_computation = algo.StdDevComputation()
std_computation.add(10.0)
self.assertRaises(exceptions.RallyException, std_computation.result)
self.assertIsNone(std_computation.result())
def test_two_values(self):
std_computation = algo.StdDevComputation()
@ -127,10 +126,10 @@ class MinComputationTestCase(test.TestCase):
self.assertRaises(TypeError, comp.add, None)
self.assertRaises(TypeError, comp.add, "str")
def test_result_raises(self):
def test_result_empty(self):
comp = algo.MinComputation()
self.assertRaises(TypeError, comp.result, 1)
self.assertRaises(exceptions.RallyException, comp.result)
self.assertIsNone(comp.result())
def test_merge(self):
single_min_algo = algo.MinComputation()
@ -166,10 +165,10 @@ class MaxComputationTestCase(test.TestCase):
self.assertRaises(TypeError, comp.add, None)
self.assertRaises(TypeError, comp.add, "str")
def test_result_raises(self):
def test_result_empty(self):
comp = algo.MaxComputation()
self.assertRaises(TypeError, comp.result, 1)
self.assertRaises(exceptions.RallyException, comp.result)
self.assertIsNone(comp.result())
def test_merge(self):
single_max_algo = algo.MaxComputation()
@ -241,10 +240,10 @@ class PercentileComputationTestCase(test.TestCase):
comp = algo.PercentileComputation(0.50, 100)
self.assertRaises(TypeError, comp.add)
def test_result_raises(self):
def test_result_empty(self):
self.assertRaises(TypeError, algo.PercentileComputation)
comp = algo.PercentileComputation(0.50, 100)
self.assertRaises(exceptions.RallyException, comp.result)
self.assertIsNone(comp.result())
class IncrementComputationTestCase(test.TestCase):