Title: [125332] trunk/Tools
Revision
125332
Author
[email protected]
Date
2012-08-10 15:17:57 -0700 (Fri, 10 Aug 2012)

Log Message

run-perf-tests should upload memory statistics to perf-o-matic
https://bugs.webkit.org/show_bug.cgi?id=93690

Reviewed by Dirk Pranke.

Upload JS Heap and FastMalloc results for a test X/Y as: X/Y:JSHeap and X/Y:FastMalloc.
Note "JS Heap" is converted to the CamelCase JSHeap.

Also did some refactoring in PerfTest.parse_output and PerfTestRunnerTest and updated
some helps in PerfTest.parse_output per arv's comments.

* Scripts/webkitpy/performance_tests/perftest.py:
(PerfTest):
(PerfTest.parse_output): Include JSHeap and FastMalloc statistics in results as well as of Time.
Also refactored it to avoid hard-coding indices in _result_classes and moved complied regular
exressions out of the function to avoid re-compiling them every time the method runs.
(PerfTest.output_statistics): Convert ':' to ': ' as well as '/'.
(ChromiumStylePerfTest.parse_output): Removed an unused variable.
* Scripts/webkitpy/performance_tests/perftestsrunner.py:
(PerfTestsRunner._parse_args): Uploaded some helps per arv's feedback.
(PerfTestsRunner._output_json_path): Extracted from _generate_and_show_results to be used in
PerfTestRunnerTest.create_runner.
(PerfTestsRunner._generate_and_show_results):
* Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
(create_runner): Extracted runner.load_output_json from various tests.
(test_run_memory_test): Added.
(PerfTestRunner): Extracted _event_target_wrapper_and_inspector_results from various tests.
(test_run_with_json_output):
(test_run_with_description):
(test_run_generates_json_by_default):
(test_run_generates_and_show_results_page):
(test_run_with_json_source):
(test_run_with_multiple_repositories):

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (125331 => 125332)


--- trunk/Tools/ChangeLog	2012-08-10 22:15:52 UTC (rev 125331)
+++ trunk/Tools/ChangeLog	2012-08-10 22:17:57 UTC (rev 125332)
@@ -1,3 +1,39 @@
+2012-08-10  Ryosuke Niwa  <[email protected]>
+
+        run-perf-tests should upload memory statistics to perf-o-matic
+        https://bugs.webkit.org/show_bug.cgi?id=93690
+
+        Reviewed by Dirk Pranke.
+
+        Upload JS Heap and FastMalloc results for a test X/Y as: X/Y:JSHeap and X/Y:FastMalloc.
+        Note "JS Heap" is converted to the CamelCase JSHeap.
+
+        Also did some refactoring in PerfTest.parse_output and PerfTestRunnerTest and updated
+        some helps in PerfTest.parse_output per arv's comments.
+
+        * Scripts/webkitpy/performance_tests/perftest.py:
+        (PerfTest):
+        (PerfTest.parse_output): Include JSHeap and FastMalloc statistics in results as well as of Time.
+        Also refactored it to avoid hard-coding indices in _result_classes and moved complied regular
+        exressions out of the function to avoid re-compiling them every time the method runs.
+        (PerfTest.output_statistics): Convert ':' to ': ' as well as '/'.
+        (ChromiumStylePerfTest.parse_output): Removed an unused variable.
+        * Scripts/webkitpy/performance_tests/perftestsrunner.py:
+        (PerfTestsRunner._parse_args): Uploaded some helps per arv's feedback.
+        (PerfTestsRunner._output_json_path): Extracted from _generate_and_show_results to be used in
+        PerfTestRunnerTest.create_runner.
+        (PerfTestsRunner._generate_and_show_results):
+        * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py:
+        (create_runner): Extracted runner.load_output_json from various tests.
+        (test_run_memory_test): Added.
+        (PerfTestRunner): Extracted _event_target_wrapper_and_inspector_results from various tests.
+        (test_run_with_json_output):
+        (test_run_with_description):
+        (test_run_generates_json_by_default):
+        (test_run_generates_and_show_results_page):
+        (test_run_with_json_source):
+        (test_run_with_multiple_repositories):
+
 2012-08-10  Benjamin Poulain  <[email protected]>
 
         Add support for String initialization from literal to WTFString

Modified: trunk/Tools/Scripts/webkitpy/performance_tests/perftest.py (125331 => 125332)


--- trunk/Tools/Scripts/webkitpy/performance_tests/perftest.py	2012-08-10 22:15:52 UTC (rev 125331)
+++ trunk/Tools/Scripts/webkitpy/performance_tests/perftest.py	2012-08-10 22:17:57 UTC (rev 125332)
@@ -111,58 +111,64 @@
                 return True
         return False
 
+    _description_regex = re.compile(r'^Description: (?P<description>.*)$', re.IGNORECASE)
+    _result_classes = ['Time', 'JS Heap', 'FastMalloc']
+    _result_class_regex = re.compile(r'^(?P<resultclass>' + r'|'.join(_result_classes) + '):')
     _statistics_keys = ['avg', 'median', 'stdev', 'min', 'max', 'unit']
-    _result_classes = ['Time:', 'JS Heap:', 'FastMalloc:']
+    _score_regex = re.compile(r'^(?P<key>' + r'|'.join(_statistics_keys) + r')\s+(?P<value>[0-9\.]+)\s*(?P<unit>.*)')
 
     def parse_output(self, output):
-        got_a_result = False
         test_failed = False
-        results = dict([(name, dict()) for name in self._result_classes])
-        score_regex = re.compile(r'^(?P<key>' + r'|'.join(self._statistics_keys) + r')\s+(?P<value>[0-9\.]+)\s*(?P<unit>.*)')
-        description_regex = re.compile(r'^Description: (?P<description>.*)$', re.IGNORECASE)
+        results = {}
+        ordered_results_keys = []
+        test_name = re.sub(r'\.\w+$', '', self._test_name)
         description_string = ""
-        result_class_regex = re.compile(r'^(?P<resultclass>' + r'|'.join(self._result_classes) + ')')
-
         result_class = ""
         for line in re.split('\n', output.text):
-            description = description_regex.match(line)
+            description = self._description_regex.match(line)
             if description:
                 description_string = description.group('description')
                 continue
 
-            result_class_match = result_class_regex.match(line)
+            result_class_match = self._result_class_regex.match(line)
             if result_class_match:
                 result_class = result_class_match.group('resultclass')
                 continue
 
-            score = score_regex.match(line)
+            score = self._score_regex.match(line)
             if score:
                 key = score.group('key')
                 value = float(score.group('value'))
                 unit = score.group('unit')
-                results[result_class]['unit'] = unit
-                results[result_class][key] = value
+                name = test_name
+                if result_class != 'Time':
+                    name += ':' + result_class.replace(' ', '')
+                if name not in ordered_results_keys:
+                    ordered_results_keys.append(name)
+                results.setdefault(name, {})
+                results[name]['unit'] = unit
+                results[name][key] = value
                 continue
 
             if not self._should_ignore_line_in_parser_test_result(line):
                 test_failed = True
                 _log.error(line)
 
-        if test_failed or set(self._statistics_keys) != set(results[self._result_classes[0]].keys()):
+        if test_failed or set(self._statistics_keys) != set(results[test_name].keys()):
             return None
 
-        test_name = re.sub(r'\.\w+$', '', self._test_name)
-        self.output_statistics(test_name, results[self._result_classes[0]], description_string)
-        if results[self._result_classes[1]] and results[self._result_classes[2]]:
-            self.output_statistics(test_name + "/JSHeap", results[self._result_classes[1]])
-            self.output_statistics(test_name + "/FastMalloc", results[self._result_classes[2]])
-        return {test_name: results['Time:']}
+        for result_name in ordered_results_keys:
+            if result_name == test_name:
+                self.output_statistics(result_name, results[result_name], description_string)
+            else:
+                self.output_statistics(result_name, results[result_name])
+        return results
 
     def output_statistics(self, test_name, results, description_string=None):
         unit = results['unit']
         if description_string:
             _log.info('DESCRIPTION: %s' % description_string)
-        _log.info('RESULT %s= %s %s' % (test_name.replace('/', ': '), results['avg'], unit))
+        _log.info('RESULT %s= %s %s' % (test_name.replace(':', ': ').replace('/', ': '), results['avg'], unit))
         _log.info(', '.join(['%s= %s %s' % (key, results[key], unit) for key in self._statistics_keys[1:5]]))
 
 
@@ -174,7 +180,6 @@
 
     def parse_output(self, output):
         test_failed = False
-        got_a_result = False
         results = {}
         for line in re.split('\n', output.text):
             resultLine = ChromiumStylePerfTest._chromium_style_result_regex.match(line)

Modified: trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py (125331 => 125332)


--- trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py	2012-08-10 22:15:52 UTC (rev 125331)
+++ trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py	2012-08-10 22:17:57 UTC (rev 125332)
@@ -99,9 +99,9 @@
             optparse.make_option("--no-results", action="" dest="generate_results", default=True,
                 help="Do no generate results JSON and results page."),
             optparse.make_option("--output-json-path",
-                help="Filename of the JSON file that summaries the results."),
+                help="Path to generate a JSON file at; may contain previous results if it already exists."),
             optparse.make_option("--source-json-path",
-                help="Path to a JSON file to be merged into the JSON file when --output-json-path is present."),
+                help="Only used on bots. Path to a JSON file to be merged into the JSON file when --output-json-path is present."),
             optparse.make_option("--description",
                 help="Add a description to the output JSON file if one is generated"),
             optparse.make_option("--no-show-results", action="" default=True, dest="show_results",
@@ -168,12 +168,15 @@
 
         return unexpected
 
+    def _output_json_path(self):
+        output_json_path = self._options.output_json_path
+        if output_json_path:
+            return output_json_path
+        return self._host.filesystem.join(self._port.perf_results_directory(), self._DEFAULT_JSON_FILENAME)
+
     def _generate_and_show_results(self):
         options = self._options
-        output_json_path = options.output_json_path
-        if not output_json_path:
-            output_json_path = self._host.filesystem.join(self._port.perf_results_directory(), self._DEFAULT_JSON_FILENAME)
-
+        output_json_path = self._output_json_path()
         output = self._generate_results_dict(self._timestamp, options.description, options.platform, options.builder_name, options.build_number)
 
         if options.source_json_path:

Modified: trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py (125331 => 125332)


--- trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py	2012-08-10 22:15:52 UTC (rev 125331)
+++ trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py	2012-08-10 22:17:57 UTC (rev 125332)
@@ -105,6 +105,31 @@
 min 1080 ms
 max 1120 ms
 """
+            elif driver_input.test_name.endswith('memory-test.html'):
+                text = """Running 20 times
+Ignoring warm-up run (1115)
+
+Time:
+avg 1100 ms
+median 1101 ms
+stdev 11 ms
+min 1080 ms
+max 1120 ms
+
+JS Heap:
+avg 832000 bytes
+median 829000 bytes
+stdev 15000 bytes
+min 811000 bytes
+max 848000 bytes
+
+FastMalloc:
+avg 532000 bytes
+median 529000 bytes
+stdev 13000 bytes
+min 511000 bytes
+max 548000 bytes
+"""
             return DriverOutput(text, '', '', '', crash=crash, timeout=timeout)
 
         def start(self):
@@ -122,6 +147,9 @@
         runner._host.filesystem.maybe_make_directory(runner._base_path, 'inspector')
         runner._host.filesystem.maybe_make_directory(runner._base_path, 'Bindings')
         runner._host.filesystem.maybe_make_directory(runner._base_path, 'Parser')
+
+        filesystem = runner._host.filesystem
+        runner.load_output_json = lambda: json.loads(filesystem.read_text_file(runner._output_json_path()))
         return runner, test_port
 
     def run_test(self, test_name):
@@ -227,6 +255,33 @@
         'median= 1101.0 ms, stdev= 11.0 ms, min= 1080.0 ms, max= 1120.0 ms',
         '', '']))
 
+    def test_run_memory_test(self):
+        runner, port = self.create_runner_and_setup_results_template()
+        runner._timestamp = 123456789
+        port.host.filesystem.write_text_file(runner._base_path + '/Parser/memory-test.html', 'some content')
+
+        output = OutputCapture()
+        output.capture_output()
+        try:
+            unexpected_result_count = runner.run()
+        finally:
+            stdout, stderr, log = output.restore_output()
+        self.assertEqual(unexpected_result_count, 0)
+        self.assertEqual(log, '\n'.join([
+            'Running 1 tests',
+            'Running Parser/memory-test.html (1 of 1)',
+            'RESULT Parser: memory-test= 1100.0 ms',
+            'median= 1101.0 ms, stdev= 11.0 ms, min= 1080.0 ms, max= 1120.0 ms',
+            'RESULT Parser: memory-test: JSHeap= 832000.0 bytes',
+            'median= 829000.0 bytes, stdev= 15000.0 bytes, min= 811000.0 bytes, max= 848000.0 bytes',
+            'RESULT Parser: memory-test: FastMalloc= 532000.0 bytes',
+            'median= 529000.0 bytes, stdev= 13000.0 bytes, min= 511000.0 bytes, max= 548000.0 bytes',
+            '', '']))
+        results = runner.load_output_json()[0]['results']
+        self.assertEqual(results['Parser/memory-test'], {'min': 1080.0, 'max': 1120.0, 'median': 1101.0, 'stdev': 11.0, 'avg': 1100.0, 'unit': 'ms'})
+        self.assertEqual(results['Parser/memory-test:JSHeap'], {'min': 811000.0, 'max': 848000.0, 'median': 829000.0, 'stdev': 15000.0, 'avg': 832000.0, 'unit': 'bytes'})
+        self.assertEqual(results['Parser/memory-test:FastMalloc'], {'min': 511000.0, 'max': 548000.0, 'median': 529000.0, 'stdev': 13000.0, 'avg': 532000.0, 'unit': 'bytes'})
+
     def _test_run_with_json_output(self, runner, filesystem, upload_suceeds=True, expected_exit_code=0):
         filesystem.write_text_file(runner._base_path + '/inspector/pass.html', 'some content')
         filesystem.write_text_file(runner._base_path + '/Bindings/event-target-wrapper.html', 'some content')
@@ -262,24 +317,25 @@
 
         return uploaded[0]
 
+    _event_target_wrapper_and_inspector_results = {
+        "Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
+        "inspector/pass.html:group_name:test_name": 42}
+
     def test_run_with_json_output(self):
         runner, port = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
             '--test-results-server=some.host'])
         self._test_run_with_json_output(runner, port.host.filesystem)
-        self.assertEqual(json.loads(port.host.filesystem.read_text_file('/mock-checkout/output.json')), {
-            "timestamp": 123456789, "results":
-            {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42},
+        self.assertEqual(runner.load_output_json(), {
+            "timestamp": 123456789, "results": self._event_target_wrapper_and_inspector_results,
             "webkit-revision": "5678", "branch": "webkit-trunk"})
 
     def test_run_with_description(self):
         runner, port = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
             '--test-results-server=some.host', '--description', 'some description'])
         self._test_run_with_json_output(runner, port.host.filesystem)
-        self.assertEqual(json.loads(port.host.filesystem.read_text_file('/mock-checkout/output.json')), {
-            "timestamp": 123456789, "description": "some description", "results":
-            {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42},
+        self.assertEqual(runner.load_output_json(), {
+            "timestamp": 123456789, "description": "some description",
+            "results": self._event_target_wrapper_and_inspector_results,
             "webkit-revision": "5678", "branch": "webkit-trunk"})
 
     def create_runner_and_setup_results_template(self, args=[]):
@@ -309,9 +365,7 @@
         self._test_run_with_json_output(runner, port.host.filesystem)
 
         self.assertEqual(json.loads(port.host.filesystem.read_text_file(output_json_path)), [{
-            "timestamp": 123456789, "results":
-            {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42},
+            "timestamp": 123456789, "results": self._event_target_wrapper_and_inspector_results,
             "webkit-revision": "5678", "branch": "webkit-trunk"}])
 
         self.assertTrue(filesystem.isfile(output_json_path))
@@ -324,9 +378,8 @@
         filesystem = port.host.filesystem
         self._test_run_with_json_output(runner, filesystem)
 
-        expected_entry = {"timestamp": 123456789, "results": {"Bindings/event-target-wrapper":
-            {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42}, "webkit-revision": "5678", "branch": "webkit-trunk"}
+        expected_entry = {"timestamp": 123456789, "results": self._event_target_wrapper_and_inspector_results,
+            "webkit-revision": "5678", "branch": "webkit-trunk"}
 
         self.maxDiff = None
         json_output = port.host.filesystem.read_text_file('/mock-checkout/output.json')
@@ -371,12 +424,9 @@
             '--source-json-path=/mock-checkout/source.json', '--test-results-server=some.host'])
         port.host.filesystem.write_text_file('/mock-checkout/source.json', '{"key": "value"}')
         self._test_run_with_json_output(runner, port.host.filesystem)
-        self.assertEqual(json.loads(port.host.filesystem.files['/mock-checkout/output.json']), {
-            "timestamp": 123456789, "results":
-            {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42},
-            "webkit-revision": "5678", "branch": "webkit-trunk",
-            "key": "value"})
+        self.assertEqual(runner.load_output_json(), {
+            "timestamp": 123456789, "results": self._event_target_wrapper_and_inspector_results,
+            "webkit-revision": "5678", "branch": "webkit-trunk", "key": "value"})
 
     def test_run_with_bad_json_source(self):
         runner, port = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
@@ -392,10 +442,8 @@
             '--test-results-server=some.host'])
         port.repository_paths = lambda: [('webkit', '/mock-checkout'), ('some', '/mock-checkout/some')]
         self._test_run_with_json_output(runner, port.host.filesystem)
-        self.assertEqual(json.loads(port.host.filesystem.files['/mock-checkout/output.json']), {
-            "timestamp": 123456789, "results":
-            {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42.0},
+        self.assertEqual(runner.load_output_json(), {
+            "timestamp": 123456789, "results": self._event_target_wrapper_and_inspector_results,
             "webkit-revision": "5678", "some-revision": "5678", "branch": "webkit-trunk"})
 
     def test_run_with_upload_json(self):
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to