-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
Conversation
2a3375b
to
ff615ea
Compare
alright I rebased this against the DNS change and things are still looking positive 👍 |
@@ -94,7 +94,7 @@ class LanternEstimatedInputLatency extends LanternMetricArtifact { | |||
}); | |||
} | |||
|
|||
return events; |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
@paulirish I rebased and added the double safeguard for insertion order 👍 |
All lantern-impacting stats remained the same after rebasing since there have been no other lantern changes since then |
There was a problem hiding this 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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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]>} */ |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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))) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const LanternFCPUI = require('../../../../gather/computed/metrics/lantern-first-cpu-idle'); | |
const LanternFCpuI = require('../../../../gather/computed/metrics/lantern-first-cpu-idle'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
never!!!! ⚔️
There was a problem hiding this comment.
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); | ||
}); | ||
}); |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
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.