[webkit-reviews] review denied: [Bug 180126] Add a test health page. : [Attachment 328751] Patch
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Dec 12 16:31:10 PST 2017
Ryosuke Niwa <rniwa at webkit.org> has denied dewei_zhu at apple.com's request for
review:
Bug 180126: Add a test health page.
https://bugs.webkit.org/show_bug.cgi?id=180126
Attachment 328751: Patch
https://bugs.webkit.org/attachment.cgi?id=328751&action=review
--- Comment #12 from Ryosuke Niwa <rniwa at webkit.org> ---
Comment on attachment 328751
--> https://bugs.webkit.org/attachment.cgi?id=328751
Patch
View in context: https://bugs.webkit.org/attachment.cgi?id=328751&action=review
This patch looks better but I think we need one more iteration of polishing
before we can land.
> Websites/perf.webkit.org/public/include/manifest-generator.php:47
> + 'warningHourBaseline' => config('warningHourBaseline'),
I don't think this variable name makes much sense. What does "baseline" mean in
this context?
> Websites/perf.webkit.org/public/v3/components/test-health-status.js:1
> +class TestHealthStatus extends ComponentBase {
I would call this FreshnessIndicator or so.
There is nothing about this component that's specific to test other than the
fact it takes platform & metric just to create a label.
We're better off creating that label in the page label and just passing in a
label for the configuration here.
> Websites/perf.webkit.org/public/v3/components/test-health-status.js:20
> + if (!this._timeForLastDataPoint)
> + this.renderReplace(this.content('container'), new SpinnerIcon);
Just add an early exit here instead of having else.
> Websites/perf.webkit.org/public/v3/components/test-health-status.js:36
> + return `${this._noCurrentDataPoint ? 'More than ' :
''}${BuildRequest.formatTimeInterval((this._measurementSetFetchTime -
this._timeForLastDataPoint) / 1000)}` +
> + `since last data point on platform: "${this._platform.name()}"
test: "${this._metric.test().fullName()}"`;
These two lines are really hard to read.
Store the results of each JS expression into a separate local variable so that
the whole string is easier to read?
If you've made the above suggestion, then you can do `~ since the last data
point for {$this._configLabel}`
where this._configLabel is `"${this._metric.test().fullName()}" for
"${this._platform.name()}"`,
which is constructed in the page component. There is no need to say test or
platform.
Names such as Speedometer and macOS would make it obvious what we're talking
about.
> Websites/perf.webkit.org/public/v3/models/build-request.js:87
> + static formatTimeInterval(intervalInSeconds) {
Could you add some unit tests for this function?
There are many tests for waitingTime in unit-tests/build-request-tests.js
ready.
So just add a few to make sure formatTimeInterval doest the same thing.
> Websites/perf.webkit.org/public/v3/models/build-request.js:125
> + const diffInSeconds = (referenceTime - this.createdAt()) / 1000;
Instead of forcing each caller to divide the number with 1000, just pass in
time in milliseconds.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:2
> +class TestHealthPage extends PageWithHeading {
I'd call this TestFreshnessPage instead because "health" can mean many things.
e.g. current test results being 50% worse than baseline might be "unhealthy"
but that's not what this page tells you.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:5
> + super('Test-Health', null);
Don't capitalize the component/page name. It should all be in lower case.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:7
> + this._checkTimeInterval = this._warningHourBaseline * 2 * 3600 *
1000;
I'd call this variable _timeDuration instead.
Time interval seems to imply more of a range (i.e. start & end) than the
duration.
e.g. https://en.wikipedia.org/wiki/Interval_(mathematics)
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:9
> + this._healthStatusForPlatformAndMetric = null;
This map doesn't store health status at all. It just stores data points in a
given platform & metric.
lastDataPointByConfiguration?
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:15
> + _loadConfig(summaryPageConfiguration) {
Nit: { should be on a new line.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:23
> + const platformIds =
[].concat(...config.platformGroups.map((platformGroup) =>
platformGroup.platforms));
> + for (const platformId of platformIds) {
Instead of flattening arrays upfront like this, you can just have a nested for
loops that go over platformGroups and platforms.
That'd make the code a lot clearer.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:36
> + const metricIds = [].concat(...[].concat(...metricsInGroup));
> + for (const metricId of metricIds) {
Ditto. Two nested concat like this is impossible to reason.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:62
> + _loadDataPointsForTests() {
Nit: _*fetch*DataPointsForTests, { should be on a new line.
Also, I'd call this _fetchTimeSeries or _fetchTestResults instead.
Data points is very specific kind of data returned by timeSeries.data() in our
codebase.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:67
> + const healthStatusByMetric = new Map;
This map doesn't store health status. It stores the time for the last data
point & url.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:77
> + let noCurrentDataPoint = false;
There is no need to have this separate boolean stored.
We can use timeForLastDataPoint === null as !noCurrentDataPoint.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:86
> + metric.id(), this._measurementSetFetchTime -
this._checkTimeInterval));
Please store the difference as a local variable, e.g. startTime instead of
duplicating the subtraction everywhere.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:87
> + healthStatusByMetric.set(metric, [timeForLastDataPoint,
noCurrentDataPoint, url]);
Use dictionary instead of an array for clarity.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:108
> + tableHeadElements.push(element('th', {class: 'diagonal-header'},
element('div', element('span', metric.test().path()[0].label()))));
Why are you creating div & span?
In general, creating wrapper elements like these is an anti-pattern.
We're better off using SVG and alike if you're trying to create a rectangle,
etc... with it.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:112
> + const [timeForLastDataPoint, noCurrentDataPoint, url] =
healthStatusForPlatformAndMetric.get(platform).get(metric) || [null, null,
null];
There is virtually no point in storing the URL earlier and using it here.
Here, we have platform, metric, and the startTime can be computed from the
instance variables.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:121
> + static _isValidPlatformMetricCombination(platform, metric,
excludedConfigurations) {
Nit: { should be on a new line.
What's the point of making this function static?
I think we're better off making it an instance method so that you don't have to
pass in excludedConfigurations.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:127
> + _constructTableCell(platform, metric, excludedConfigurations,
timeForLastDataPoint, noCurrentDataPoint, url) {
Nit: { should be on a new line.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:133
> + return element('td', {class: 'status-cell'}, new
TestHealthStatus(platform, metric, this._warningHourBaseline,
this._measurementSetFetchTime, timeForLastDataPoint, noCurrentDataPoint, url));
Instead of re-creating the entire table each time, we should simply construct
the table once,
and then for each status component, we should update its value in a separate
loop.
In subsequent calls to render(), we would only execute that second loop.
> Websites/perf.webkit.org/public/v3/pages/test-health-page.js:169
> + #test-health th.diagonal-header > div > span {
We shouldn't have a span just so that can have a border line this. That's an
anti-pattern.
More information about the webkit-reviews
mailing list