Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core(simulator): start nodes in observed order #5362

Merged
merged 14 commits into from
Oct 23, 2018

Conversation

patrickhulce
Copy link
Collaborator

@patrickhulce patrickhulce commented May 25, 2018

I'm gonna let this one chill for a bit until I do more investigation, but basically I'm seeing graphs with some strange order and want to explore if this helps.

Big improvements to TTI tail error and not much change elsewhere. This should also make the smoketest savings much more reproducible/understandable.

image

@patrickhulce patrickhulce changed the title core(simulator): start nodes in priority order core(simulator): start nodes in observed order Jul 11, 2018
@patrickhulce
Copy link
Collaborator Author

alright I rebased this against the DNS change and things are still looking positive 👍

@@ -94,7 +94,7 @@ class LanternEstimatedInputLatency extends LanternMetricArtifact {
});
}

return events;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow the flow perfectly but it seems like the new sorting in simulator would make this one redundant. But no?
(if not, could this one be done earlier within a more common location?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's redundant if the nodes all start in the order that they were queued (which used to always be true), but necessary in other cases. Even if it were true though, the fact that the .entries iterator on a map returns this in insertion order feels like an impl detail I wouldn't want important pieces of the codebase to rely on knowing since it bit me here once it changed slightly :/

I'm generally comfortable with the idea that consumers of a Map who need the results sorted going forward need to sort it themselves. As a safeguard though, I'm cool with also sorting the map before we return it based on start time. Sound good compromise?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind the double sort (which will get better when timsort in the latest V8 lands in Node), but it is going to be difficult to remember to always do this. Love this:

As a safeguard though, I'm cool with also sorting the map before we return it based on start time.

FWIW insertion-order iteration is called out very clearly for Map and Set (unlike previous iteration order issues in JS).

Maybe put a jsdoc comment on nodeTimings that insertion/iteration order is sorted based on startTime so at least the knowledge is out there somewhere?

@@ -56,6 +56,7 @@ class LanternFirstCPUIdle extends LanternInteractive {
longTasks.push({start: timing.startTime, end: timing.endTime});
}

longTasks.sort((a, b) => a.start - b.start);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question. can we do the sort earlier in a more generic location?

I want to avoid the situation where someone writes a new audit and forgets they gotta sort on their own.

@patrickhulce
Copy link
Collaborator Author

@paulirish I rebased and added the double safeguard for insertion order 👍

@patrickhulce
Copy link
Collaborator Author

All lantern-impacting stats remained the same after rebasing since there have been no other lantern changes since then

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is looking good to me. Mostly some nits and a request for a test

* @param {Node[]} nodes
* @return {Node[]}
*/
_sortNodesByStartTime(nodes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe _getNodesSortedByStartTime or something to indicate it's returning a new thing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

_computeFinalNodeTimings() {
/** @type {Map<Node, LH.Gatherer.Simulation.NodeTiming>} */
const nodeTimings = new Map();
/** @type {Array<[CpuNode | NetworkNode, LH.Gatherer.Simulation.NodeTiming]>} */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CpuNode | NetworkNode -> Node? (looks like it works in the return type, at least)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -419,7 +435,7 @@ class Simulator {
// loop as long as we have nodes in the queue or currently in progress
while (nodesReadyToStart.size || nodesInProgress.size) {
// move all possible queued nodes to in progress
for (const node of nodesReadyToStart) {
for (const node of this._sortNodesByStartTime(Array.from(nodesReadyToStart))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe make _sortNodesByStartTime take a Set and have Array.from called internally there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -94,7 +94,7 @@ class LanternEstimatedInputLatency extends LanternMetricArtifact {
});
}

return events;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind the double sort (which will get better when timsort in the latest V8 lands in Node), but it is going to be difficult to remember to always do this. Love this:

As a safeguard though, I'm cool with also sorting the map before we return it based on start time.

FWIW insertion-order iteration is called out very clearly for Map and Set (unlike previous iteration order issues in JS).

Maybe put a jsdoc comment on nodeTimings that insertion/iteration order is sorted based on startTime so at least the knowledge is out there somewhere?

}

return nodeTimings;
// Most consumers will want the entries sorted by startTime, so insert them in that order
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@@ -8,6 +8,7 @@
const LanternFirstCPUIdle = require('../../../../gather/computed/metrics/lantern-first-cpu-idle.js'); // eslint-disable-line max-len
const assert = require('assert');

const LanternFCPUI = require('../../../../gather/computed/metrics/lantern-first-cpu-idle');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const LanternFCPUI = require('../../../../gather/computed/metrics/lantern-first-cpu-idle');
const LanternFCpuI = require('../../../../gather/computed/metrics/lantern-first-cpu-idle');

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never!!!! ⚔️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☠️😁😀 they need a "reject suggestion with prejudice" button


assert.equal(LanternFCPUI.getFirstCPUIdleWindowStart(tasks, 0), 700);
});
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be harder to set up, but maybe a Simulator test that reads in artifacts and similarly asserts that nodeTimings are in startTime order (and wouldn't have been before this change)? I think our stableSort test for a trace has caught at least one regression that was accidentally reordering traces :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(or maybe there's an easier way to unit test it without calling private stuff; I didn't look very hard :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@patrickhulce patrickhulce changed the title core(simulator): start nodes in observed order core(simulator): start nodes in observed order Oct 23, 2018
@patrickhulce patrickhulce merged commit 253053f into master Oct 23, 2018
@patrickhulce patrickhulce deleted the lantern_priority_order branch October 23, 2018 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants