New perf dashboard UI tries to fetch commits all the time
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Oct 2014 03:45:20 +0000 (03:45 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Oct 2014 03:45:20 +0000 (03:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137592

Reviewed by Andreas Kling.

Added hasReportedCommits boolean to repository meta data in manifest.json, and used that in
the front end to avoid issuing HTTP requests to fetch commit logs for repositories with
no reported commits as they are all going to fail.

Also added an internal cache to FetchCommitsForTimeRange in the front end to avoid fetching
the same commit logs repeatedly. There are two data structures we cache: commitsByRevision
which maps a given commit revision/hash to a commit object; and commitsByTime which is an array
of commits sorted chronologically by time.

* public/include/manifest.php:

* public/v2/app.js:
(App.CommitsViewerComponent.commitsChanged):

* public/v2/data.js:
(FetchCommitsForTimeRange):
(FetchCommitsForTimeRange._cachedCommitsByRepository):

* public/v2/manifest.js:
(App.Repository):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174555 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Websites/perf.webkit.org/ChangeLog
Websites/perf.webkit.org/public/include/manifest.php
Websites/perf.webkit.org/public/v2/app.js
Websites/perf.webkit.org/public/v2/data.js
Websites/perf.webkit.org/public/v2/manifest.js

index fe6b755..b5156b9 100644 (file)
@@ -1,3 +1,31 @@
+2014-10-09  Ryosuke Niwa  <rniwa@webkit.org>
+
+        New perf dashboard UI tries to fetch commits all the time
+        https://bugs.webkit.org/show_bug.cgi?id=137592
+
+        Reviewed by Andreas Kling.
+
+        Added hasReportedCommits boolean to repository meta data in manifest.json, and used that in
+        the front end to avoid issuing HTTP requests to fetch commit logs for repositories with
+        no reported commits as they are all going to fail.
+
+        Also added an internal cache to FetchCommitsForTimeRange in the front end to avoid fetching
+        the same commit logs repeatedly. There are two data structures we cache: commitsByRevision
+        which maps a given commit revision/hash to a commit object; and commitsByTime which is an array
+        of commits sorted chronologically by time.
+
+        * public/include/manifest.php:
+
+        * public/v2/app.js:
+        (App.CommitsViewerComponent.commitsChanged):
+
+        * public/v2/data.js:
+        (FetchCommitsForTimeRange):
+        (FetchCommitsForTimeRange._cachedCommitsByRepository):
+
+        * public/v2/manifest.js:
+        (App.Repository):
+
 2014-10-08  Ryosuke Niwa  <rniwa@webkit.org>
 
         Another unreviewed build fix after r174477.
index 1c7e4f3..c91cb1d 100644 (file)
@@ -15,12 +15,18 @@ class ManifestGenerator {
         $config_table = $this->db->fetch_table('test_configurations');
         $platform_table = $this->db->fetch_table('platforms');
         $repositories_table = $this->db->fetch_table('repositories');
+
+        $repositories_with_commit = $this->db->query_and_fetch_all(
+            'SELECT DISTINCT(commit_repository) FROM commits WHERE commit_reported IS TRUE') or array();
+        foreach ($repositories_with_commit as &$row)
+            $row = $row['commit_repository'];
+
         $this->manifest = array(
             'tests' => $this->tests(),
             'metrics' => $this->metrics(),
             'all' => $this->platforms($config_table, $platform_table, false),
             'dashboard' => $this->platforms($config_table, $platform_table, true),
-            'repositories' => $this->repositories($repositories_table),
+            'repositories' => $this->repositories($repositories_table, $repositories_with_commit),
             'builders' => $this->builders(),
             'bugTrackers' => $this->bug_trackers($repositories_table),
         );
@@ -85,12 +91,16 @@ class ManifestGenerator {
         return $platforms;
     }
 
-    private function repositories($repositories_table) {
+    private function repositories($repositories_table, $repositories_with_commit) {
         $repositories = array();
         if (!$repositories_table)
             return $repositories;
-        foreach ($repositories_table as $row)
-            $repositories[$row['repository_name']] = array('url' => $row['repository_url'], 'blameUrl' => $row['repository_blame_url']);
+        foreach ($repositories_table as $row) {
+            $repositories[$row['repository_name']] = array(
+                'url' => $row['repository_url'],
+                'blameUrl' => $row['repository_blame_url'],
+                'hasReportedCommits' => in_array($row['repository_id'], $repositories_with_commit));
+        }
 
         return $repositories;
     }
index c46bacc..f48ed4c 100755 (executable)
@@ -1408,7 +1408,7 @@ App.CommitsViewerComponent = Ember.Component.extend({
         var to = revisionInfo.get('currentRevision');
         var from = revisionInfo.get('previousRevision') || to;
         var repository = this.get('repository');
-        if (!from || !repository)
+        if (!from || !repository || !repository.get('hasReportedCommits'))
             return;
 
         var self = this;
index ad02b37..32d52f2 100755 (executable)
@@ -1,15 +1,44 @@
 // We don't use DS.Model for these object types because we can't afford to process millions of them.
 
-FetchCommitsForTimeRange = function (repository, from, to)
+function FetchCommitsForTimeRange(repository, from, to)
 {
     var url = '../api/commits/' + repository.get('id') + '/' + from + '-' + to;
-    console.log('Fetching ' + url)
+
+    var cachedCommits = FetchCommitsForTimeRange._cachedCommitsByRepository[repository];
+    if (!cachedCommits) {
+        cachedCommits = {commitsByRevision: {}, commitsByTime: []};
+        FetchCommitsForTimeRange._cachedCommitsByRepository[repository] = cachedCommits;
+    }
+
+    if (cachedCommits) {
+        var startCommit = cachedCommits.commitsByRevision[from];
+        var endCommit = cachedCommits.commitsByRevision[to];
+        if (startCommit && endCommit) {
+            return new Ember.RSVP.Promise(function (resolve) {
+                resolve(cachedCommits.commitsByTime.slice(startCommit.index, endCommit.index + 1)) });
+        }
+    }
+
+    console.log('Fecthing ' + url);
+
     return new Ember.RSVP.Promise(function (resolve, reject) {
         $.getJSON(url, function (data) {
             if (data.status != 'OK') {
                 reject(data.status);
                 return;
             }
+
+            data.commits.forEach(function (commit) {
+                if (cachedCommits.commitsByRevision[commit.revision])
+                    return;
+                commit.time = new Date(commit.time.replace(' ', 'T'));
+                cachedCommits.commitsByRevision[commit.revision] = commit;
+                cachedCommits.commitsByTime.push(commit);
+            });
+
+            cachedCommits.commitsByTime.sort(function (a, b) { return a.time - b.time; });
+            cachedCommits.commitsByTime.forEach(function (commit, index) { commit.index = index; });
+
             resolve(data.commits);
         }).fail(function (xhr, status, error) {
             reject(xhr.status + (error ? ', ' + error : ''));
@@ -17,6 +46,8 @@ FetchCommitsForTimeRange = function (repository, from, to)
     });
 }
 
+FetchCommitsForTimeRange._cachedCommitsByRepository = {};
+
 function Measurement(rawData)
 {
     this._raw = rawData;
index 6283a58..b10c0be 100755 (executable)
@@ -72,6 +72,7 @@ App.Platform = App.NameLabelModel.extend({
 App.Repository = App.NameLabelModel.extend({
     url: DS.attr('string'),
     blameUrl: DS.attr('string'),
+    hasReportedCommits: DS.attr('boolean'),
     urlForRevision: function (currentRevision) {
         return (this.get('url') || '').replace(/\$1/g, currentRevision);
     },