-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Network: force array order when sorting hierarchical levels #3576
Conversation
Fixes #340r34. If coordinates are not available to sort within a hierarchical level, sort to array order instead. The previous fix on this issue was not good enough to circumvent this quirk in the chromium sorting. This should bury it.
// Test on 'undefined' takes care of divergent behaviour in chrome | ||
if (a.y === undefined || b.y === undefined) return 0; // THIS HAPPENS | ||
if (a.y === undefined || b.y === undefined) { | ||
return idOrder[a.id] - idOrder[b.id]; |
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.
Could you use return nodeArray.indexOf(a) - nodeArray.indexOf(b)
instead of creating idOrder
?
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.
That was my first attempt. It doesn't work because the array get changed inline as the sorting runs.
So the indexing may change on every call to the custom sort()
- and it does on chrome, even if there's no reason to change it. That's the quirk this issue tries to work around.
Basically, the fix is to register the initial sorting order and retain that by default.
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.
Why are the x or y values ever undefined
?
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 come from the options. They are user-defined starting positions, not required. They can be undefined
for that reason.
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 am somewhat uncomfortable with the idea of having to iterate this array twice in order to sort it.
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.
If the user specifies an undefined position, can we assign it a position, so that by the time it reaches this sort code, it'll never be undefined?
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.
What about just comparing a.id
against b.id
in the case that x or y is undefined?
I see no way of escaping it. But it's not too bad. First iteration is linear, second O(n*log(n)) if the implementers did their work right. Feel free to make a suggestion for improvement.
An option could be to make the collection of id order chrome only.
|
Copying the array with Object.assign would work as well. Would that be faster?
|
Related issue https://bugs.chromium.org/p/v8/issues/detail?id=90 for reference. |
This very sort routine is part of that determination of positions. It precedes the actual assignments.
You should keep in mind that initial positions *may* be assigned. Networks with some nodes having predefined positions and some not are possible.
|
Id's are also user-definable. You could use strings with your favorite singer names for them (real world example). The id's imply nothing about position.
|
It's true that the ids are not guaranteed to sort in an expected order, but the example shown uses sortable ids, and I think that is what most people use (ie, monotonically increasing integers). So we should optimize for that case. Optionally we could provide a way for users to use |
No, sorry, disagree with this. Users insert what they damn well please. Integers is just a very special case.
Hokay, this could be workable. So adding an option to be able to select a stable sort. |
Unfortunately we do not have the actual data to back up how users id their nodes in the wild. However, if it's going to be arbitrarily sorted anyways, making it sort consistently for integer-based ids makes sense to me - especially given the issue reporter's example. From what I've read, timsort is the best alternative... However, even it has 38% slow-down. I agree with the decision of the Chrome team to provide a fast unstable sort as the default. edit: Also to note, the vast majority of our network examples, themselves also use monotonically increasing integers as ids. |
Well, I've got a pretty clear idea from all the examples I've collected from the issues. From my point of view, integer id's are the exception. You want me to take samples from the code of 76 issues I have at hand? I just added some links to previous comment; perhaps they are of use. First link appears to be more efficient that what I have thought up. The other two just look interesting. |
I'd like to throw https://www.npmjs.com/package/timsort into the running (benchmarks included on the page) |
Yeah. That looks good. Edit: Very good indeed. Not only stable, but faster than default sort, at least in If this beats chrome's sort, then it's a no-brainer. |
Ah nice, the benchmark is on github. We will test this in chrome. |
Here are the results of the timsort benchmark when run on chromium. Compare these with the values on the timsort page.
Not too shabby. Most speedups are less than with |
While I'm at it, here are the values for firefox.
Interestingly, firefox does a better job at sorting than chrome. |
It looks like |
That's true, but it is a fairly straightforward implementation of a well-known algorithm. |
OK made the switch. Interestingly, there was only one other location within |
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.
Just a couple nits, otherwise looks good.
* even if the custom sort function returns 0. | ||
* | ||
* For this reason, an external sort implementation is used, | ||
* which has the added benefit of being faster of the standard |
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.
"... of being faster than the ..."
@@ -30,6 +29,8 @@ | |||
* The layout is a way to arrange the nodes in the view; this can be done | |||
* on non-hierarchical networks as well. The converse is also possible. | |||
*/ | |||
'use strict'; |
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.
Why move this
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.
No special reason, other than to keep the javascript code together. You'd rather have it on top?
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.
Fine as is, just curious
…3576) * Network: force array order when sorting hierarchical levels Fixes #340r34. If coordinates are not available to sort within a hierarchical level, sort to array order instead. The previous fix on this issue was not good enough to circumvent this quirk in the chromium sorting. This should bury it. * Added TimSort for sorting in DirectionStrategy * Added TimSort to LayoutEngine * Fixed typo
Fixes #3403.
Fixes #3542.
If coordinates are not available to sort within a hierarchical level, sort to array order instead.
The previous fix on this issue was not good enough to circumvent this quirk in the chromium sorting. This should bury it.