Merge "vts framework-side changes for wifi target-side tests"
diff --git a/proto/VtsReportMessage.proto b/proto/VtsReportMessage.proto
index f9dca10..6aa3694 100644
--- a/proto/VtsReportMessage.proto
+++ b/proto/VtsReportMessage.proto
@@ -55,6 +55,8 @@
VTS_PROFILING_TYPE_TIMESTAMP = 1;
// for multiple single-type samples with labels.
VTS_PROFILING_TYPE_LABELED_VECTOR = 2;
+ // for multiple single-type samples without labels.
+ VTS_PROFILING_TYPE_UNLABELED_VECTOR = 3;
}
// To specify a call flow event.
diff --git a/proto/VtsReportMessage_pb2.py b/proto/VtsReportMessage_pb2.py
index 758d336..78925bd 100644
--- a/proto/VtsReportMessage_pb2.py
+++ b/proto/VtsReportMessage_pb2.py
@@ -14,7 +14,7 @@
DESCRIPTOR = _descriptor.FileDescriptor(
name='VtsReportMessage.proto',
package='android.vts',
- serialized_pb='\n\x16VtsReportMessage.proto\x12\x0b\x61ndroid.vts\"\xe0\x01\n\x18\x41ndroidDeviceInfoMessage\x12\x14\n\x0cproduct_type\x18\x01 \x01(\x0c\x12\x17\n\x0fproduct_variant\x18\x02 \x01(\x0c\x12\x14\n\x0c\x62uild_flavor\x18\x0b \x01(\x0c\x12\x10\n\x08\x62uild_id\x18\x0c \x01(\x0c\x12\x0e\n\x06\x62ranch\x18\x15 \x01(\x0c\x12\x13\n\x0b\x62uild_alias\x18\x16 \x01(\x0c\x12\x11\n\tapi_level\x18\x1f \x01(\x0c\x12\x10\n\x08\x61\x62i_name\x18\x33 \x01(\x0c\x12\x13\n\x0b\x61\x62i_bitness\x18\x34 \x01(\x0c\x12\x0e\n\x06serial\x18\x65 \x01(\x0c\"g\n\x10\x41ndroidBuildInfo\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x0b \x01(\x0c\x12\x12\n\nbuild_type\x18\x0c \x01(\x0c\x12\x0e\n\x06\x62ranch\x18\r \x01(\x0c\x12\x15\n\rbuild_summary\x18\x15 \x01(\x0c\"\x1f\n\x0bVtsHostInfo\x12\x10\n\x08hostname\x18\x01 \x01(\x0c\"\xab\x02\n\x15TestCaseReportMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x30\n\x0btest_result\x18\x0b \x01(\x0e\x32\x1b.android.vts.TestCaseResult\x12\x17\n\x0fstart_timestamp\x18\x15 \x01(\x03\x12\x15\n\rend_timestamp\x18\x16 \x01(\x03\x12\x34\n\x08\x63overage\x18\x1f \x03(\x0b\x32\".android.vts.CoverageReportMessage\x12\x36\n\tprofiling\x18) \x03(\x0b\x32#.android.vts.ProfilingReportMessage\x12\x34\n\x08systrace\x18* \x03(\x0b\x32\".android.vts.SystraceReportMessage\"\xa0\x02\n\x16ProfilingReportMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12+\n\x04type\x18\x02 \x01(\x0e\x32\x1d.android.vts.VtsProfilingType\x12@\n\x0fregression_mode\x18\x03 \x01(\x0e\x32\'.android.vts.VtsProfilingRegressionMode\x12\x17\n\x0fstart_timestamp\x18\x0b \x01(\x03\x12\x15\n\rend_timestamp\x18\x0c \x01(\x03\x12\r\n\x05label\x18\x15 \x03(\x0c\x12\r\n\x05value\x18\x16 \x03(\x03\x12\x14\n\x0cx_axis_label\x18\x1f \x01(\x0c\x12\x14\n\x0cy_axis_label\x18 \x01(\x0c\x12\x0f\n\x07options\x18) \x03(\x0c\";\n\x15SystraceReportMessage\x12\x14\n\x0cprocess_name\x18\x01 \x01(\x0c\x12\x0c\n\x04html\x18\x0b \x03(\x0c\"\xe5\x01\n\x15\x43overageReportMessage\x12\x11\n\tfile_path\x18\x0b \x01(\x0c\x12\x14\n\x0cproject_name\x18\x0c \x01(\x0c\x12\x10\n\x08revision\x18\r \x01(\x0c\x12\x1c\n\x14line_coverage_vector\x18\x17 \x03(\x05\x12\x18\n\x10total_line_count\x18\x65 \x01(\x05\x12\x1a\n\x12\x63overed_line_count\x18\x66 \x01(\x05\x12\x14\n\x08\x64ir_path\x18\x01 \x01(\x0c\x42\x02\x18\x01\x12\x15\n\tfile_name\x18\x02 \x01(\x0c\x42\x02\x18\x01\x12\x10\n\x04html\x18\x03 \x01(\x0c\x42\x02\x18\x01\"\xa3\x04\n\x11TestReportMessage\x12\x12\n\ntest_suite\x18\x01 \x01(\x0c\x12\x0c\n\x04test\x18\x02 \x01(\x0c\x12+\n\ttest_type\x18\x03 \x01(\x0e\x32\x18.android.vts.VtsTestType\x12:\n\x0b\x64\x65vice_info\x18\x04 \x03(\x0b\x32%.android.vts.AndroidDeviceInfoMessage\x12\x31\n\nbuild_info\x18\x05 \x01(\x0b\x32\x1d.android.vts.AndroidBuildInfo\x12\x18\n\x10subscriber_email\x18\x06 \x03(\x0c\x12+\n\thost_info\x18\x07 \x01(\x0b\x32\x18.android.vts.VtsHostInfo\x12\x35\n\ttest_case\x18\x0b \x03(\x0b\x32\".android.vts.TestCaseReportMessage\x12\x36\n\tprofiling\x18\x15 \x03(\x0b\x32#.android.vts.ProfilingReportMessage\x12\x34\n\x08systrace\x18\x16 \x03(\x0b\x32\".android.vts.SystraceReportMessage\x12\x17\n\x0fstart_timestamp\x18\x65 \x01(\x03\x12\x15\n\rend_timestamp\x18\x66 \x01(\x03\x12\x34\n\x08\x63overage\x18g \x03(\x0b\x32\".android.vts.CoverageReportMessage*\xb3\x01\n\x0eTestCaseResult\x12\x12\n\x0eUNKNOWN_RESULT\x10\x00\x12\x19\n\x15TEST_CASE_RESULT_PASS\x10\x01\x12\x19\n\x15TEST_CASE_RESULT_FAIL\x10\x02\x12\x19\n\x15TEST_CASE_RESULT_SKIP\x10\x03\x12\x1e\n\x1aTEST_CASE_RESULT_EXCEPTION\x10\x04\x12\x1c\n\x18TEST_CASE_RESULT_TIMEOUT\x10\x05*\x9c\x01\n\x0bVtsTestType\x12\x18\n\x14UNKNOWN_VTS_TESTTYPE\x10\x00\x12\x1e\n\x1aVTS_HOST_DRIVEN_STRUCTURAL\x10\x01\x12\x1b\n\x17VTS_HOST_DRIVEN_FUZZING\x10\x02\x12\x19\n\x15VTS_TARGET_SIDE_GTEST\x10\x03\x12\x1b\n\x17VTS_TARGET_SIDE_FUZZING\x10\x04*\xa3\x01\n\x1aVtsProfilingRegressionMode\x12\x1b\n\x17UNKNOWN_REGRESSION_MODE\x10\x00\x12 \n\x1cVTS_REGRESSION_MODE_DISABLED\x10\x01\x12\"\n\x1eVTS_REGRESSION_MODE_INCREASING\x10\x02\x12\"\n\x1eVTS_REGRESSION_MODE_DECREASING\x10\x03*{\n\x10VtsProfilingType\x12\x1e\n\x1aUNKNOWN_VTS_PROFILING_TYPE\x10\x00\x12 \n\x1cVTS_PROFILING_TYPE_TIMESTAMP\x10\x01\x12%\n!VTS_PROFILING_TYPE_LABELED_VECTOR\x10\x02\x42)\n\x15\x63om.android.vts.protoB\x10VtsReportMessage')
+ serialized_pb='\n\x16VtsReportMessage.proto\x12\x0b\x61ndroid.vts\"\xe0\x01\n\x18\x41ndroidDeviceInfoMessage\x12\x14\n\x0cproduct_type\x18\x01 \x01(\x0c\x12\x17\n\x0fproduct_variant\x18\x02 \x01(\x0c\x12\x14\n\x0c\x62uild_flavor\x18\x0b \x01(\x0c\x12\x10\n\x08\x62uild_id\x18\x0c \x01(\x0c\x12\x0e\n\x06\x62ranch\x18\x15 \x01(\x0c\x12\x13\n\x0b\x62uild_alias\x18\x16 \x01(\x0c\x12\x11\n\tapi_level\x18\x1f \x01(\x0c\x12\x10\n\x08\x61\x62i_name\x18\x33 \x01(\x0c\x12\x13\n\x0b\x61\x62i_bitness\x18\x34 \x01(\x0c\x12\x0e\n\x06serial\x18\x65 \x01(\x0c\"g\n\x10\x41ndroidBuildInfo\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x0b \x01(\x0c\x12\x12\n\nbuild_type\x18\x0c \x01(\x0c\x12\x0e\n\x06\x62ranch\x18\r \x01(\x0c\x12\x15\n\rbuild_summary\x18\x15 \x01(\x0c\"\x1f\n\x0bVtsHostInfo\x12\x10\n\x08hostname\x18\x01 \x01(\x0c\"\xab\x02\n\x15TestCaseReportMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12\x30\n\x0btest_result\x18\x0b \x01(\x0e\x32\x1b.android.vts.TestCaseResult\x12\x17\n\x0fstart_timestamp\x18\x15 \x01(\x03\x12\x15\n\rend_timestamp\x18\x16 \x01(\x03\x12\x34\n\x08\x63overage\x18\x1f \x03(\x0b\x32\".android.vts.CoverageReportMessage\x12\x36\n\tprofiling\x18) \x03(\x0b\x32#.android.vts.ProfilingReportMessage\x12\x34\n\x08systrace\x18* \x03(\x0b\x32\".android.vts.SystraceReportMessage\"\xa0\x02\n\x16ProfilingReportMessage\x12\x0c\n\x04name\x18\x01 \x01(\x0c\x12+\n\x04type\x18\x02 \x01(\x0e\x32\x1d.android.vts.VtsProfilingType\x12@\n\x0fregression_mode\x18\x03 \x01(\x0e\x32\'.android.vts.VtsProfilingRegressionMode\x12\x17\n\x0fstart_timestamp\x18\x0b \x01(\x03\x12\x15\n\rend_timestamp\x18\x0c \x01(\x03\x12\r\n\x05label\x18\x15 \x03(\x0c\x12\r\n\x05value\x18\x16 \x03(\x03\x12\x14\n\x0cx_axis_label\x18\x1f \x01(\x0c\x12\x14\n\x0cy_axis_label\x18 \x01(\x0c\x12\x0f\n\x07options\x18) \x03(\x0c\";\n\x15SystraceReportMessage\x12\x14\n\x0cprocess_name\x18\x01 \x01(\x0c\x12\x0c\n\x04html\x18\x0b \x03(\x0c\"\xe5\x01\n\x15\x43overageReportMessage\x12\x11\n\tfile_path\x18\x0b \x01(\x0c\x12\x14\n\x0cproject_name\x18\x0c \x01(\x0c\x12\x10\n\x08revision\x18\r \x01(\x0c\x12\x1c\n\x14line_coverage_vector\x18\x17 \x03(\x05\x12\x18\n\x10total_line_count\x18\x65 \x01(\x05\x12\x1a\n\x12\x63overed_line_count\x18\x66 \x01(\x05\x12\x14\n\x08\x64ir_path\x18\x01 \x01(\x0c\x42\x02\x18\x01\x12\x15\n\tfile_name\x18\x02 \x01(\x0c\x42\x02\x18\x01\x12\x10\n\x04html\x18\x03 \x01(\x0c\x42\x02\x18\x01\"\xa3\x04\n\x11TestReportMessage\x12\x12\n\ntest_suite\x18\x01 \x01(\x0c\x12\x0c\n\x04test\x18\x02 \x01(\x0c\x12+\n\ttest_type\x18\x03 \x01(\x0e\x32\x18.android.vts.VtsTestType\x12:\n\x0b\x64\x65vice_info\x18\x04 \x03(\x0b\x32%.android.vts.AndroidDeviceInfoMessage\x12\x31\n\nbuild_info\x18\x05 \x01(\x0b\x32\x1d.android.vts.AndroidBuildInfo\x12\x18\n\x10subscriber_email\x18\x06 \x03(\x0c\x12+\n\thost_info\x18\x07 \x01(\x0b\x32\x18.android.vts.VtsHostInfo\x12\x35\n\ttest_case\x18\x0b \x03(\x0b\x32\".android.vts.TestCaseReportMessage\x12\x36\n\tprofiling\x18\x15 \x03(\x0b\x32#.android.vts.ProfilingReportMessage\x12\x34\n\x08systrace\x18\x16 \x03(\x0b\x32\".android.vts.SystraceReportMessage\x12\x17\n\x0fstart_timestamp\x18\x65 \x01(\x03\x12\x15\n\rend_timestamp\x18\x66 \x01(\x03\x12\x34\n\x08\x63overage\x18g \x03(\x0b\x32\".android.vts.CoverageReportMessage*\xb3\x01\n\x0eTestCaseResult\x12\x12\n\x0eUNKNOWN_RESULT\x10\x00\x12\x19\n\x15TEST_CASE_RESULT_PASS\x10\x01\x12\x19\n\x15TEST_CASE_RESULT_FAIL\x10\x02\x12\x19\n\x15TEST_CASE_RESULT_SKIP\x10\x03\x12\x1e\n\x1aTEST_CASE_RESULT_EXCEPTION\x10\x04\x12\x1c\n\x18TEST_CASE_RESULT_TIMEOUT\x10\x05*\x9c\x01\n\x0bVtsTestType\x12\x18\n\x14UNKNOWN_VTS_TESTTYPE\x10\x00\x12\x1e\n\x1aVTS_HOST_DRIVEN_STRUCTURAL\x10\x01\x12\x1b\n\x17VTS_HOST_DRIVEN_FUZZING\x10\x02\x12\x19\n\x15VTS_TARGET_SIDE_GTEST\x10\x03\x12\x1b\n\x17VTS_TARGET_SIDE_FUZZING\x10\x04*\xa3\x01\n\x1aVtsProfilingRegressionMode\x12\x1b\n\x17UNKNOWN_REGRESSION_MODE\x10\x00\x12 \n\x1cVTS_REGRESSION_MODE_DISABLED\x10\x01\x12\"\n\x1eVTS_REGRESSION_MODE_INCREASING\x10\x02\x12\"\n\x1eVTS_REGRESSION_MODE_DECREASING\x10\x03*\xa4\x01\n\x10VtsProfilingType\x12\x1e\n\x1aUNKNOWN_VTS_PROFILING_TYPE\x10\x00\x12 \n\x1cVTS_PROFILING_TYPE_TIMESTAMP\x10\x01\x12%\n!VTS_PROFILING_TYPE_LABELED_VECTOR\x10\x02\x12\'\n#VTS_PROFILING_TYPE_UNLABELED_VECTOR\x10\x03\x42)\n\x15\x63om.android.vts.protoB\x10VtsReportMessage')
_TESTCASERESULT = _descriptor.EnumDescriptor(
name='TestCaseResult',
@@ -136,11 +136,15 @@
name='VTS_PROFILING_TYPE_LABELED_VECTOR', index=2, number=2,
options=None,
type=None),
+ _descriptor.EnumValueDescriptor(
+ name='VTS_PROFILING_TYPE_UNLABELED_VECTOR', index=3, number=3,
+ options=None,
+ type=None),
],
containing_type=None,
options=None,
- serialized_start=2347,
- serialized_end=2470,
+ serialized_start=2348,
+ serialized_end=2512,
)
VtsProfilingType = enum_type_wrapper.EnumTypeWrapper(_VTSPROFILINGTYPE)
@@ -162,6 +166,7 @@
UNKNOWN_VTS_PROFILING_TYPE = 0
VTS_PROFILING_TYPE_TIMESTAMP = 1
VTS_PROFILING_TYPE_LABELED_VECTOR = 2
+VTS_PROFILING_TYPE_UNLABELED_VECTOR = 3
diff --git a/runners/host/base_test_with_webdb.py b/runners/host/base_test_with_webdb.py
index 450871a..e13bf59 100644
--- a/runners/host/base_test_with_webdb.py
+++ b/runners/host/base_test_with_webdb.py
@@ -415,21 +415,23 @@
self._profiling[name].end_timestamp = self.GetTimestamp()
return True
- def AddProfilingDataLabeledVector(
+ def AddProfilingDataVector(
self,
name,
labels,
values,
+ data_type,
options=[],
x_axis_label="x-axis",
y_axis_label="y-axis",
regression_mode=ReportMsg.VTS_REGRESSION_MODE_INCREASING):
- """Adds the profiling data in order to upload to the web DB.
+ """Adds the vector profiling data in order to upload to the web DB.
Args:
name: string, profiling point name.
- labels: a list of labels.
- values: a list of values.
+ labels: a list or set of labels.
+ values: a list or set of values where each value is an integer.
+ data_type: profiling data type.
options: a set of options.
x-axis_label: string, the x-axis label title for a graph plot.
y-axis_label: string, the y-axis label title for a graph plot.
@@ -446,23 +448,83 @@
self._profiling[name] = self._report_msg.profiling.add()
self._profiling[name].name = name
- self._profiling[
- name].type = ReportMsg.VTS_PROFILING_TYPE_LABELED_VECTOR
+ self._profiling[name].type = data_type
self._profiling[name].regression_mode = regression_mode
- for label, value in zip(labels, values):
- self._profiling[name].label.append(label)
- self._profiling[name].value.append(value)
+ if labels:
+ self._profiling[name].label.extend(labels)
+ self._profiling[name].value.extend(values)
self._profiling[name].x_axis_label = x_axis_label
self._profiling[name].y_axis_label = y_axis_label
- for option in options:
- self._profiling[name].options.append(option)
+ self._profiling[name].options.extend(options)
- def AddProfilingDataLabeledPoint(self, name, value):
- """Adds labeled point type profiling data for uploading to the web DB.
+ def AddProfilingDataLabeledVector(
+ self,
+ name,
+ labels,
+ values,
+ options=[],
+ x_axis_label="x-axis",
+ y_axis_label="y-axis",
+ regression_mode=ReportMsg.VTS_REGRESSION_MODE_INCREASING):
+ """Adds the labeled vector profiling data in order to upload to the web DB.
Args:
name: string, profiling point name.
- value: int, the value.
+ labels: a list or set of labels.
+ values: a list or set of values where each value is an integer.
+ options: a set of options.
+ x-axis_label: string, the x-axis label title for a graph plot.
+ y-axis_label: string, the y-axis label title for a graph plot.
+ regression_mode: specifies the direction of change which indicates
+ performance regression.
+ """
+ self.AddProfilingDataVector(name, labels, values,
+ ReportMsg.VTS_PROFILING_TYPE_LABELED_VECTOR,
+ options, x_axis_label, y_axis_label,
+ regression_mode)
+
+ def AddProfilingDataUnlabeledVector(
+ self,
+ name,
+ values,
+ options=[],
+ x_axis_label="x-axis",
+ y_axis_label="y-axis",
+ regression_mode=ReportMsg.VTS_REGRESSION_MODE_INCREASING):
+ """Adds the unlabeled vector profiling data in order to upload to the web DB.
+
+ Args:
+ name: string, profiling point name.
+ values: a list or set of values where each value is an integer.
+ options: a set of options.
+ x-axis_label: string, the x-axis label title for a graph plot.
+ y-axis_label: string, the y-axis label title for a graph plot.
+ regression_mode: specifies the direction of change which indicates
+ performance regression.
+ """
+ self.AddProfilingDataVector(name, None, values,
+ ReportMsg.VTS_PROFILING_TYPE_UNLABELED_VECTOR,
+ options, x_axis_label, y_axis_label,
+ regression_mode)
+
+ def AddProfilingDataTimestamp(
+ self,
+ name,
+ value,
+ options=[],
+ x_axis_label="x-axis",
+ y_axis_label="y-axis",
+ regression_mode=ReportMsg.VTS_REGRESSION_MODE_INCREASING):
+ """Adds the named point type profiling data in order to upload to the web DB.
+
+ Args:
+ name: string, profiling point name.
+ value: integer, the value.
+ options: a set of options.
+ x-axis_label: string, the x-axis label title for a graph plot.
+ y-axis_label: string, the y-axis label title for a graph plot.
+ regression_mode: specifies the direction of change which indicates
+ performance regression.
"""
if not getattr(self, self.USE_GAE_DB, False):
logging.error("'use_gae_db' config is not True.")
@@ -474,9 +536,12 @@
self._profiling[name] = self._report_msg.profiling.add()
self._profiling[name].name = name
self._profiling[name].type = ReportMsg.VTS_PROFILING_TYPE_TIMESTAMP
+ self._profiling[name].regression_mode = regression_mode
self._profiling[name].start_timestamp = 0
self._profiling[name].end_timestamp = value
- return True
+ self._profiling[name].x_axis_label = x_axis_label
+ self._profiling[name].y_axis_label = y_axis_label
+ self._profiling[name].options.extend(options)
def IsCoverageConfigSpecified(self):
"""Determines if the config file specifies modules for coverage.
@@ -651,8 +716,6 @@
"""
merged_profiling_data = profiling_utils.VTSProfilingData()
for data in self._profiling_data:
- if data.name:
- merged_profiling_data.name = data.name
for item in data.options:
merged_profiling_data.options.add(item)
for api, latences in data.values.items():
@@ -661,23 +724,9 @@
else:
merged_profiling_data.values[api] = latences
for api, latencies in merged_profiling_data.values.items():
- if latencies:
- merged_profiling_data.labels.append(api)
- merged_profiling_data.aggregated_values["max"].append(
- max(latencies))
- merged_profiling_data.aggregated_values["min"].append(
- min(latencies))
- merged_profiling_data.aggregated_values["avg"].append(
- sum(latencies) / len(latencies))
- for tag in [_MAX, _MIN, _AVG]:
- if merged_profiling_data.name is None:
- name = tag
- else:
- name = merged_profiling_data.name + "_" + tag
- self.AddProfilingDataLabeledVector(
- name,
- merged_profiling_data.labels,
- merged_profiling_data.aggregated_values[tag],
+ self.AddProfilingDataUnlabeledVector(
+ api,
+ latencies,
merged_profiling_data.options,
- x_axis_label="API name",
- y_axis_label="API processing latency (nana secs)")
+ x_axis_label="API processing latency (nano secs)",
+ y_axis_label="Frequency")
diff --git a/tools/vts-tradefed/res/config/vts-serving-staging-hal-hidl-profiling.xml b/tools/vts-tradefed/res/config/vts-serving-staging-hal-hidl-profiling.xml
index b481f4e..956534c 100644
--- a/tools/vts-tradefed/res/config/vts-serving-staging-hal-hidl-profiling.xml
+++ b/tools/vts-tradefed/res/config/vts-serving-staging-hal-hidl-profiling.xml
@@ -27,6 +27,7 @@
<option name="compatibility:include-filter" value="VrHidlTargetProfilingTest" />
<option name="compatibility:include-filter" value="HalMemtrackHidlTargetProfilingTest" />
<option name="compatibility:include-filter" value="HalGatekeeperHidlTargetBasicProfilingTest" />
- <option name="compatibility:include-filter" value="HalBootHidlTargetProfilingTest" />
+ <!--TODO: re-enable when VTS can handle device/hal incompatibility -->
+ <!-- <option name="compatibility:include-filter" value="HalBootHidlTargetProfilingTest" /> -->
<template-include name="reporters" default="basic-reporters" />
</configuration>
diff --git a/utils/python/cpu/cpu_frequency_scaling.py b/utils/python/cpu/cpu_frequency_scaling.py
index a292d88..f29f37b 100644
--- a/utils/python/cpu/cpu_frequency_scaling.py
+++ b/utils/python/cpu/cpu_frequency_scaling.py
@@ -104,9 +104,11 @@
["cat /sys/devices/system/cpu/cpu%s/cpufreq/scaling_max_freq" % cpu_no,
"cat /sys/devices/system/cpu/cpu%s/cpufreq/scaling_cur_freq" % cpu_no])
asserts.assertEqual(2, len(results[const.STDOUT]))
- asserts.assertFalse(
- any(results[const.EXIT_CODE]),
- "Can't check the current and/or max CPU frequency.")
+ if any(results[const.EXIT_CODE]):
+ logging.error("Can't check the current and/or max CPU frequency.")
+ logging.error("Stderr for scaling_max_freq: %s", results[const.STDERR][0])
+ logging.error("Stderr for scaling_cur_freq: %s", results[const.STDERR][1])
+ return True
configurable_max_frequency = results[const.STDOUT][0].strip()
current_frequency = results[const.STDOUT][1].strip()
if configurable_max_frequency != current_frequency:
diff --git a/utils/python/mirror/hal_mirror.py b/utils/python/mirror/hal_mirror.py
index cba4220..c8e7146 100644
--- a/utils/python/mirror/hal_mirror.py
+++ b/utils/python/mirror/hal_mirror.py
@@ -159,7 +159,7 @@
target_component_name=None,
target_basepaths=_DEFAULT_TARGET_BASE_PATHS,
handler_name=None,
- hw_binder_service_name=_DEFAULT_TARGET_BASE_PATHS,
+ hw_binder_service_name=_DEFAULT_HWBINDER_SERVICE,
bits=64):
"""Initiates a handler for a particular HIDL HAL.
diff --git a/utils/python/profiling/profiling_utils.py b/utils/python/profiling/profiling_utils.py
index 29537f4..deb423a 100644
--- a/utils/python/profiling/profiling_utils.py
+++ b/utils/python/profiling/profiling_utils.py
@@ -59,19 +59,13 @@
"""Class to store the VTS profiling data.
Attributes:
- name: A string to describe the profiling data. e.g. server_side_latency.
- labels: A list of profiling data labels. e.g. a list of api names.
values: A dict that stores the profiling data. e.g. latencies of each api.
- aggregated_values: A dict that stores the aggregated profiling data.
options: A set of strings where each string specifies an associated
option (which is the form of 'key=value').
"""
def __init__(self):
- self.name = None
self.values = {}
- self.labels = []
- self.aggregated_values = {"avg": [], "max": [], "min": []}
self.options = set()
@@ -143,12 +137,6 @@
latencies.append(
long(time_stamps[index]) - long(time_stamps[index - 1]))
profiling_data.values[api] = latencies
- for api, latencies in profiling_data.values.items():
- if latencies:
- profiling_data.labels.append(api)
- profiling_data.aggregated_values["max"].append(max(latencies))
- profiling_data.aggregated_values["min"].append(min(latencies))
- profiling_data.aggregated_values["avg"].append(sum(latencies) / len(latencies))
return profiling_data
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/proto/VtsReportMessage.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/proto/VtsReportMessage.java
index 55078a7..d8558f1 100644
--- a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/proto/VtsReportMessage.java
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/proto/VtsReportMessage.java
@@ -392,6 +392,14 @@
* </pre>
*/
VTS_PROFILING_TYPE_LABELED_VECTOR(2, 2),
+ /**
+ * <code>VTS_PROFILING_TYPE_UNLABELED_VECTOR = 3;</code>
+ *
+ * <pre>
+ * for multiple single-type samples without labels.
+ * </pre>
+ */
+ VTS_PROFILING_TYPE_UNLABELED_VECTOR(3, 3),
;
/**
@@ -414,6 +422,14 @@
* </pre>
*/
public static final int VTS_PROFILING_TYPE_LABELED_VECTOR_VALUE = 2;
+ /**
+ * <code>VTS_PROFILING_TYPE_UNLABELED_VECTOR = 3;</code>
+ *
+ * <pre>
+ * for multiple single-type samples without labels.
+ * </pre>
+ */
+ public static final int VTS_PROFILING_TYPE_UNLABELED_VECTOR_VALUE = 3;
public final int getNumber() { return value; }
@@ -423,6 +439,7 @@
case 0: return UNKNOWN_VTS_PROFILING_TYPE;
case 1: return VTS_PROFILING_TYPE_TIMESTAMP;
case 2: return VTS_PROFILING_TYPE_LABELED_VECTOR;
+ case 3: return VTS_PROFILING_TYPE_UNLABELED_VECTOR;
default: return null;
}
}
@@ -13205,11 +13222,12 @@
"essionMode\022\033\n\027UNKNOWN_REGRESSION_MODE\020\000\022" +
" \n\034VTS_REGRESSION_MODE_DISABLED\020\001\022\"\n\036VTS" +
"_REGRESSION_MODE_INCREASING\020\002\022\"\n\036VTS_REG" +
- "RESSION_MODE_DECREASING\020\003*{\n\020VtsProfilin" +
- "gType\022\036\n\032UNKNOWN_VTS_PROFILING_TYPE\020\000\022 \n",
- "\034VTS_PROFILING_TYPE_TIMESTAMP\020\001\022%\n!VTS_P" +
- "ROFILING_TYPE_LABELED_VECTOR\020\002B)\n\025com.an" +
- "droid.vts.protoB\020VtsReportMessage"
+ "RESSION_MODE_DECREASING\020\003*\244\001\n\020VtsProfili" +
+ "ngType\022\036\n\032UNKNOWN_VTS_PROFILING_TYPE\020\000\022 ",
+ "\n\034VTS_PROFILING_TYPE_TIMESTAMP\020\001\022%\n!VTS_" +
+ "PROFILING_TYPE_LABELED_VECTOR\020\002\022\'\n#VTS_P" +
+ "ROFILING_TYPE_UNLABELED_VECTOR\020\003B)\n\025com." +
+ "android.vts.protoB\020VtsReportMessage"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/ShowGraphServlet.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
index 4e4d3e7..c26c753 100644
--- a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/ShowGraphServlet.java
@@ -23,6 +23,7 @@
import com.android.vts.util.BigtableHelper;
import com.android.vts.util.Graph;
import com.android.vts.util.GraphSerializer;
+import com.android.vts.util.Histogram;
import com.android.vts.util.LineGraph;
import com.android.vts.util.PerformanceUtil;
import org.apache.hadoop.hbase.TableName;
@@ -58,31 +59,52 @@
private static final String HIDL_HAL_OPTION = "hidl_hal_mode";
private static final String[] splitKeysArray = new String[]{HIDL_HAL_OPTION};
- private static final Set<String> splitKeySet = new HashSet<String>(Arrays.asList(splitKeysArray));
+ private static final Set<String> splitKeySet =
+ new HashSet<String>(Arrays.asList(splitKeysArray));
private static final String PROFILING_DATA_ALERT = "No profiling data was found.";
private static final long MILLI_TO_MICRO = 1000; // conversion factor from milli to micro units
/**
- * Process a profiling report message and determine which graph to insert the point into.
+ * Process a profiling report message and determine which line graph to insert the point into.
* @param profilingReportMessage The profiling report to process.
* @param idString The ID derived from the test run to identify the profiling report.
* @param graphMap A map from graph name to Graph object.
*/
- private static void processLabeledListReport(
+ private static void processLineGraphReport(
ProfilingReportMessage profilingReportMessage, String idString,
Map<String, Graph> graphMap) {
if (profilingReportMessage.getLabelList().size() == 0 ||
profilingReportMessage.getLabelList().size() !=
profilingReportMessage.getValueList().size()) return;
- String name = PerformanceUtil.getOptionKeys(profilingReportMessage.getOptionsList(), splitKeySet);
+ String name = PerformanceUtil.getOptionKeys(profilingReportMessage.getOptionsList(),
+ splitKeySet);
if (!graphMap.containsKey(name)) {
graphMap.put(name, new LineGraph(name));
}
graphMap.get(name).addData(idString, profilingReportMessage);
}
+ /**
+ * Process a profiling report message and determine which histogram to insert the point into.
+ * @param profilingReportMessage The profiling report to process.
+ * @param graphMap A map from graph name to Graph object.
+ */
+ private static void processHistogramReport(
+ ProfilingReportMessage profilingReportMessage, String idString,
+ Map<String, Graph> graphMap) {
+ if (profilingReportMessage.getValueList().size() == 0 &&
+ profilingReportMessage.getStartTimestamp() >= profilingReportMessage.getEndTimestamp())
+ return;
+ String name = PerformanceUtil.getOptionKeys(
+ profilingReportMessage.getOptionsList(), splitKeySet);
+ if (!graphMap.containsKey(name)) {
+ graphMap.put(name, new Histogram(name));
+ }
+ graphMap.get(name).addData(idString, profilingReportMessage);
+ }
+
@Override
public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException {
@@ -105,9 +127,6 @@
tableName = TableName.valueOf(TABLE_PREFIX + request.getParameter("testName"));
table = BigtableHelper.getTable(tableName);
- // This list holds the values for all profiling points.
- List<Double> profilingPointValuesList = new ArrayList<>();
-
// Set of device names
Set<String> deviceSet = new HashSet<String>();
@@ -124,7 +143,8 @@
AndroidDeviceInfoMessage firstDeviceInfo = testReportMessage.getDeviceInfoList().get(0);
String firstDeviceBuildId = firstDeviceInfo.getBuildId().toStringUtf8();
- String firstDeviceType = firstDeviceInfo.getProductVariant().toStringUtf8().toLowerCase();
+ String firstDeviceType =
+ firstDeviceInfo.getProductVariant().toStringUtf8().toLowerCase();
String idString = firstDeviceType + " (" + firstDeviceBuildId + ")";
deviceSet.add(firstDeviceType);
if (selectedDevice != null && !firstDeviceType.equals(selectedDevice)) continue;
@@ -138,9 +158,13 @@
switch(profilingReportMessage.getType()) {
case UNKNOWN_VTS_PROFILING_TYPE:
case VTS_PROFILING_TYPE_TIMESTAMP:
- continue;
+ processHistogramReport(profilingReportMessage, idString, graphMap);
+ break;
case VTS_PROFILING_TYPE_LABELED_VECTOR:
- processLabeledListReport(profilingReportMessage, idString, graphMap);
+ processLineGraphReport(profilingReportMessage, idString, graphMap);
+ break;
+ case VTS_PROFILING_TYPE_UNLABELED_VECTOR:
+ processHistogramReport(profilingReportMessage, idString, graphMap);
break;
default :
break;
@@ -155,12 +179,6 @@
graphList.add(graphMap.get(name));
}
- // fill performance profiling array
- double[] performanceProfilingValues = new double[profilingPointValuesList.size()];
- for (int i = 0; i < profilingPointValuesList.size(); i++) {
- performanceProfilingValues[i] = profilingPointValuesList.get(i).doubleValue();
- }
-
// sort devices list
if (!deviceSet.contains(selectedDevice)) selectedDevice = null;
String[] devices = deviceSet.toArray(new String[deviceSet.size()]);
@@ -172,7 +190,8 @@
request.setAttribute("selectedDevice", selectedDevice);
if (graphList.size() == 0) request.setAttribute("error", PROFILING_DATA_ALERT);
- Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Graph.class, new GraphSerializer()).create();
+ Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(
+ Graph.class, new GraphSerializer()).create();
request.setAttribute("graphs", gson.toJson(graphList));
request.setAttribute("profilingPointName", profilingPointName);
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Graph.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Graph.java
index 6a9ea6b..e808451 100644
--- a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Graph.java
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Graph.java
@@ -27,6 +27,8 @@
public static final String VALUE_KEY = "values";
public static final String X_LABEL_KEY = "x_label";
+ public static final String Y_LABEL_KEY = "y_label";
+ public static final String IDS_KEY = "ids";
public static final String NAME_KEY = "name";
public static final String TYPE_KEY = "type";
@@ -48,6 +50,12 @@
public abstract String getXLabel();
/**
+ * Get the y axis label.
+ * @return The y axis label.
+ */
+ public abstract String getYLabel();
+
+ /**
* Get the name of the graph.
* @return The name of the graph.
*/
@@ -67,6 +75,7 @@
public JsonObject toJson() {
JsonObject json = new JsonObject();
json.add(X_LABEL_KEY, new JsonPrimitive(getXLabel()));
+ json.add(Y_LABEL_KEY, new JsonPrimitive(getYLabel()));
json.add(NAME_KEY, new JsonPrimitive(getName()));
json.add(TYPE_KEY, new JsonPrimitive(getType().toString()));
return json;
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Histogram.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Histogram.java
new file mode 100644
index 0000000..ab870ea
--- /dev/null
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/Histogram.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You may
+ * obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.vts.util;
+
+import com.android.vts.proto.VtsReportMessage.ProfilingReportMessage;
+import com.google.common.primitives.Doubles;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.math3.stat.descriptive.rank.Percentile;
+
+/**
+ * Helper object for describing graph data.
+ */
+public class Histogram extends Graph {
+
+ public static final String PERCENTILES_KEY = "percentiles";
+ public static final String PERCENTILE_VALUES_KEY = "percentile_values";
+
+ private List<Double> values;
+ private List<String> ids;
+ private String xLabel;
+ private String yLabel;
+ private String name;
+ private GraphType type = GraphType.HISTOGRAM;
+
+ public Histogram(String name) {
+ this.name = name;
+ this.values = new ArrayList<>();
+ this.ids = new ArrayList<>();
+ }
+
+ /**
+ * Get the x axis label.
+ * @return The x axis label.
+ */
+ @Override
+ public String getXLabel() {
+ return xLabel;
+ }
+
+ /**
+ * Get the graph type.
+ * @return The graph type.
+ */
+ @Override
+ public GraphType getType() {
+ return type;
+ }
+
+ /**
+ * Get the name of the graph.
+ * @return The name of the graph.
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the y axis label.
+ * @return The y axis label.
+ */
+ @Override
+ public String getYLabel() {
+ return yLabel;
+ }
+
+ /**
+ * Add data to the graph.
+ * @param id The name of the graph.
+ * @param profilingReport The profiling report message containing data to add.
+ */
+ @Override
+ public void addData(String id, ProfilingReportMessage profilingReport) {
+ if (profilingReport.getValueList().size() == 0 &&
+ profilingReport.getStartTimestamp() >= profilingReport.getEndTimestamp()) return;
+ xLabel = profilingReport.getXAxisLabel().toStringUtf8();
+ yLabel = profilingReport.getYAxisLabel().toStringUtf8();
+ for (long value : profilingReport.getValueList()) {
+ values.add((double) value);
+ ids.add(id);
+ }
+ if (profilingReport.getStartTimestamp() != profilingReport.getEndTimestamp() &&
+ profilingReport.getStartTimestamp() < profilingReport.getEndTimestamp()) {
+ values.add((double) profilingReport.getEndTimestamp() -
+ profilingReport.getStartTimestamp());
+ ids.add(id);
+ }
+ }
+
+ /**
+ * Serializes the graph to json format.
+ * @return A JsonElement object representing the graph object.
+ */
+ @Override
+ public JsonObject toJson() {
+ int[] percentiles = {1, 5, 10, 20, 25, 50, 75, 80, 90, 95, 99};
+ double[] percentileValues = new double[percentiles.length];
+ double[] valueList = Doubles.toArray(values);
+ for (int i = 0; i < percentiles.length; i++) {
+ percentileValues[i] =
+ Math.round(new Percentile().evaluate(valueList, percentiles[i]) * 1000d) / 1000d;
+ }
+ JsonObject json = super.toJson();
+ json.add(VALUE_KEY, new Gson().toJsonTree(values).getAsJsonArray());
+ json.add(PERCENTILES_KEY, new Gson().toJsonTree(percentiles).getAsJsonArray());
+ json.add(PERCENTILE_VALUES_KEY, new Gson().toJsonTree(percentileValues).getAsJsonArray());
+ json.add(IDS_KEY, new Gson().toJsonTree(ids).getAsJsonArray());
+ return json;
+ }
+}
+
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/LineGraph.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/LineGraph.java
index e496ee0..a6ed50d 100644
--- a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/LineGraph.java
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/util/LineGraph.java
@@ -19,7 +19,6 @@
import com.android.vts.proto.VtsReportMessage.ProfilingReportMessage;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -30,9 +29,7 @@
*/
public class LineGraph extends Graph {
- private static final String Y_LABEL_KEY = "y_label";
- private static final String IDS_KEY = "ids";
- private static final String TICKS_KEY = "ticks";
+ public static final String TICKS_KEY = "ticks";
private List<ProfilingReportMessage> profilingReports;
private List<String> ids;
@@ -78,6 +75,7 @@
* Get the y axis label.
* @return The y axis label.
*/
+ @Override
public String getYLabel() {
return yLabel;
}
@@ -131,7 +129,6 @@
}
}
json.add(VALUE_KEY, new Gson().toJsonTree(lineGraphValues).getAsJsonArray());
- json.add(Y_LABEL_KEY, new JsonPrimitive(getYLabel()));
json.add(IDS_KEY, new Gson().toJsonTree(ids).getAsJsonArray());
json.add(TICKS_KEY, new Gson().toJsonTree(axisTicks));
return json;
diff --git a/web/dashboard/appengine/servlet/src/main/webapp/css/show_graph.css b/web/dashboard/appengine/servlet/src/main/webapp/css/show_graph.css
index 4de017a..44b2a2d 100644
--- a/web/dashboard/appengine/servlet/src/main/webapp/css/show_graph.css
+++ b/web/dashboard/appengine/servlet/src/main/webapp/css/show_graph.css
@@ -47,12 +47,23 @@
padding-bottom: 25px;
}
-.graph {
+.graph-wrapper {
padding: 30px;
- height: 550px;
}
-#percentile-table-div {
- margin-bottom: 20px;
+.graph {
+ height: 500px;
+ padding-bottom: 30px;
+}
+
+.percentile-table {
+ width: auto;
+ margin: auto;
+}
+
+.percentile-table td, th{
+ font-size: 12px;
+ text-align: center;
+ padding: 5px 10px;
}
diff --git a/web/dashboard/appengine/servlet/src/main/webapp/show_graph.jsp b/web/dashboard/appengine/servlet/src/main/webapp/show_graph.jsp
index 8cf8fc3..e9b8301 100644
--- a/web/dashboard/appengine/servlet/src/main/webapp/show_graph.jsp
+++ b/web/dashboard/appengine/servlet/src/main/webapp/show_graph.jsp
@@ -36,30 +36,43 @@
<script type='text/javascript'>
if (${analytics_id}) analytics_init(${analytics_id});
google.charts.load('current', {packages:['corechart', 'table', 'line']});
- google.charts.setOnLoadCallback(drawAllLineGraphs);
- google.charts.setOnLoadCallback(function() {
- $('.gradient').removeClass('gradient');
- });
+ google.charts.setOnLoadCallback(drawAllGraphs);
+ ONE_DAY = 86400000000;
MICRO_PER_MILLI = 1000;
$(function() {
$('select').material_select();
var date = $('#date').datepicker({
- showAnim: 'slideDown',
- maxDate: new Date()
- });
+ showAnim: 'slideDown',
+ maxDate: new Date()
+ });
date.datepicker('setDate', new Date(${startTime} / MICRO_PER_MILLI));
$('#load').click(load);
});
- function drawAllLineGraphs() {
+ // Draw all graphs.
+ function drawAllGraphs() {
var graphs = ${graphs};
graphs.forEach(function(graph) {
if (graph.type == 'LINE_GRAPH') drawLineGraph(graph);
+ else if (graph.type == 'HISTOGRAM') drawHistogram(graph);
});
}
+ /**
+ * Draw a line graph.
+ *
+ * Args:
+ * lineGraph: a JSON object containing the following fields:
+ * - name: the name of the graph
+ * - values: an array of numbers
+ * - ticks: an array of strings to use as x-axis labels
+ * - ids: an array of string labels for each point (e.g. the
+ * build info for the run that produced the point)
+ * - x_label: the string label for the x axis
+ * - y_label: the string label for the y axis
+ */
function drawLineGraph(lineGraph) {
var title = 'Performance';
if (lineGraph.name) title += ' (' + lineGraph.name + ')';
@@ -70,7 +83,7 @@
lineGraph.values[i].unshift(label);
});
var data = new google.visualization.DataTable();
- data.addColumn('string', lineGraph.x_value);
+ data.addColumn('string', lineGraph.x_label);
lineGraph.ids.forEach(function(id) {
data.addColumn('number', id);
});
@@ -82,14 +95,120 @@
},
legend: { position: 'none' }
};
- var container = $('<div class="row card center-align col s12 graph"></div>');
+ var container = $('<div class="row card center-align col s12 graph-wrapper"></div>');
container.appendTo('#profiling-container');
- var chart = new google.charts.Line(container[0]);
+ var chartDiv = $('<div class="col s12 graph"></div>');
+ chartDiv.appendTo(container);
+ var chart = new google.charts.Line(chartDiv[0]);
chart.draw(data, options);
}
+ /**
+ * Draw a histogram.
+ *
+ * Args:
+ * hist: a JSON object containing the following fields:
+ * - name: the name of the graph
+ * - values: an array of numbers
+ * - ids: an array of string labels for each point (e.g. the
+ * build info for the run that produced the point)
+ * - x_label: the string label for the x axis
+ * - y_label: the string label for the y axis
+ */
+ function drawHistogram(hist) {
+ test = hist;
+ var title = 'Performance';
+ if (hist.name) title += ' (' + hist.name + ')';
+ var values = hist.values;
+ var histogramData = values.map(function(d, i) {
+ return [hist.ids[i], d];
+ });
+ var min = Math.min.apply(null, values),
+ max = Math.max.apply(null, values);
+
+ var histogramTicks = new Array(10);
+ var delta = (max - min) / 10;
+ for (var i = 0; i <= 10; i++) {
+ histogramTicks[i] = Math.round(min + delta * i);
+ }
+
+ var data = google.visualization.arrayToDataTable(histogramData, true);
+
+ var options = {
+ title: title,
+ titleTextStyle: {
+ color: '#757575',
+ fontSize: 16,
+ bold: false
+ },
+ legend: { position: 'none' },
+ colors: ['#4285F4'],
+ fontName: 'Roboto',
+ vAxis:{
+ title: hist.y_label,
+ titleTextStyle: {
+ color: '#424242',
+ fontSize: 12,
+ italic: false
+ },
+ textStyle: {
+ fontSize: 12,
+ color: '#757575'
+ },
+ },
+ hAxis: {
+ ticks: histogramTicks,
+ title: hist.x_label,
+ textStyle: {
+ fontSize: 12,
+ color: '#757575'
+ },
+ titleTextStyle: {
+ color: '#424242',
+ fontSize: 12,
+ italic: false
+ }
+ },
+ bar: { gap: 0 },
+ histogram: {
+ maxNumBuckets: 200,
+ minValue: min * 0.95,
+ maxValue: max * 1.05
+ },
+ chartArea: {
+ width: '100%',
+ top: 40,
+ left: 50,
+ height: '80%'
+ }
+ };
+ var container = $('<div class="row card col s12 graph-wrapper"></div>');
+ container.appendTo('#profiling-container');
+
+ var chartDiv = $('<div class="col s12 graph"></div>');
+ chartDiv.appendTo(container);
+ var chart = new google.visualization.Histogram(chartDiv[0]);
+ chart.draw(data, options);
+
+ var tableDiv = $('<div class="col s12"></div>');
+ tableDiv.appendTo(container);
+
+ var tableHtml = '<table class="percentile-table"><thead><tr>';
+ hist.percentiles.forEach(function(p) {
+ tableHtml += '<th data-field="id">' + p + '%</th>';
+ });
+ tableHtml += '</tr></thead><tbody><tr>';
+ hist.percentile_values.forEach(function(v) {
+ tableHtml += '<td>' + v + '</td>';
+ });
+ tableHtml += '</tbody></table>';
+ $(tableHtml).appendTo(tableDiv);
+ }
+
+ // Reload the page.
function load() {
var startTime = $('#date').datepicker('getDate').getTime();
+ startTime = startTime + (ONE_DAY / MICRO_PER_MILLI) - 1;
var ctx = '${pageContext.request.contextPath}';
var link = ctx + '/show_graph?profilingPoint=${profilingPointName}' +
'&testName=${testName}' +