Claudia Hernández
June 01, 2018
220

# How to sort your socks using JS

No matter your experience in JS, you have probably came across the Array#sort method at some point. Do you remember the first time you tried sorting numbers? You were probably astonished that the sort method does not sort things out quite as we might expect. Believe it or not, there is actually much more going on than meets the eye! Let’s get our computer science hat on and explore some useful sorting algorithms currently implemented by JS engines used by Node such as Chrome's V8 and Microsoft's Chakra. As a developer, learning how these algorithms work, why and when to use them will help you create more performant and consistent applications!

June 01, 2018

## Transcript

1. HOW TO SORT YOUR
SOCKS USING
JAVASCRIPT?
Claudia Hernandez
-
AmsterdamJS

2. CS 101
Intro to computational
complexity:
The Sorting Problem

3. @koste4
http://www.bbc.com/news/magazine-37196037

4. @koste4
¿WHAT DOES A PILE OF
DIRTY SOCKS
NAPOLEON STRATEGIES &
ROMANIAN FOLK
DANCE
,
HAVE IN
COMMON?

5. @koste4
COMPUTATIONAL
COMPLEXITY
Study of all the possible
algorithms that can solve a
problem

6. @koste4
Algorithm that sorts elements of
a list according to a certain
order. The most commonly used
orders are numerical &
lexicographical
SORTING
ALGORTHIM

7. @koste4
ARRAY SORT IN JS
#
1 myArray = [33, 2, 98, 25, 4]
2 myArray.sort() // [ 2, 25, 33, 4, 98 ]

8. @koste4
LEXICOGRAPHICAL
SORTING
“If compareFunction is not supplied,
elements are sorted by converting them to
strings and comparing strings in Unicode
code point value”
compareFunction
D

9. @koste4
UNICODE VALUE
1 colors = ['red', 'blue']
2 colors.sort()
3 // ['blue', 'red']
4
5 numbers = [80, 9]
6 numbers.sort()
7 // [80, 9]
80
=
=
56 48
57 00
9

10. @koste4
1 colors = ['red', 'blue']
2 colors.sort()
3 // ['blue', 'red']
4
5 numbers = ['80', '9']
6 numbers.sort()
7 // [80, 9]
80
=
=
56 48
57 00
9
UNICODE VALUE

11. @koste4
ARRAY SORT IN JS
#
1 // [ 2, 25, 33, 4, 98 ]

12. @koste4
ARRAY SORT IN JS
#
1 emojis = ["", "", ""]
2 emojis.sort() // [ "", "", ""]
4
5 wtfJavascript = [390, "", 1, "2325"]
6 wtfJavascript.sort() // [ 1, "235", 390, ""]

13. @koste4
ARRAY SORT IN JS
#
1 myArray = [33, 2, 98, 25, 4]
2 myArray.sort( (a,b) => a - b )
3 // [ 2, 4, 25, 33, 98 ]

14. @koste4
¿HAVE YOU EVER
WHICH
WONDERED
ALGORITHIM IS USED
IN JAVASCRIPT’S
NATIVE SORT FUNCTION ?
JAVASCRIPT

15. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp
M E R G E S O R T
S O R T
S P I D E R
M O N K E Y

16. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp
M E R G E S O R T
S O R T
S P I D E R
M O N K E Y

17. https://hg.mozilla.org/mozilla-central/ﬁle/28be8df0deb7/js/src/jsarray.cpp
M E R G E S O R T
S O R T
S P I D E R
M O N K E Y

18. https://github.com/v8/v8/blob/master/src/js/array.js
Q U I C K S O R T
S O R T
V 8

19. https://github.com/v8/v8/blob/master/src/js/array.js
Q U I C K S O R T
S O R T
V 8

20. https://trac.webkit.org/browser/trunk/Source/JavaScriptCore/
builtins/ArrayPrototype.js
M E R G E S O R T
N I T R O

21. https://github.com/Microsoft/ChakraCore/blob/master/
lib/Common/DataStructures/QuickSort.h
Q U I C K S O R T
S O R T
C H A K R A

22. @koste4
JS Engine Sort Algorithm
SpiderMonkey
F I R E F O X
Insertion Sort (for short arrays)
Merge Sort
V8
C H R O M E
Insertion Sort (for short arrays)
Quick Sort
Nitro
S A FA R I
Merge Sort
Chakra
I N T E R N E T E X P L O R E R
QuickSort

23. @koste4
SORTING
ALGORITHMS

24. @koste4
STABILITY
A stable sort is one in which
equivalent elements retain
their relative positions after
sorting

25. @koste4
Insertion Sort
3
Merge Sort
Quick Sort
1
2

26. @koste4
INSERTION SORT
The array is searched sequentially and unsorted items are moved
and inserted into a sorted sub-list kept within the same array.

27. 27
1 function InsertionSort(arr) {
2
3 let len = arr.length, // number of items in the array
4 value, // the value currently being compared
5 i, // index into unsorted section
6 j; // index into sorted section
7
8 for(i = 1; i < len; i++) {
9
10 // store the current value because it may shift later
11 value = arr[i]
12
13 // Whenever the value in the sorted section is greater than the value
14 // in the unsorted section, shift all items in the sorted section over
15 // by one. This creates space in which to insert the value.
16 for (j = i - 1; j >= 0 && arr[j] > value; j--) {
17 arr[j+1] = arr[j]
18 }
19 arr[j+1] = value
20 }
21
22 return arr
23
24 }

28. @koste4
10 LOC

29. @koste4
DIVIDE & CONQUER
Napoleonic tactics
"Military genius"
Divide the enemy in halves
& surprise them individually
1
3
2
Conquer (attack) the enemy
since it'll be reduced to half its
size
Concentrate resources in a
single problem

30. @koste4
MERGE SORT
Divide the array into 2 subarrays
each with n/2 elements
1
3
2
Conquer each subarray by
sorting it. Unless the array is
sufficiently small, use recursion
to do this
Combine the solutions to the
subarrays by merging them into
a single sorted array

31. @koste4
MERGE SORT

32. 32
1 function MergeSort(arr) {
2
3 let len = arr.length, // number of items in the array
4 middle, // middle of the array
5 left, // left side of the array
6 right // right side of the array
7
8 // Arrays with 0 or 1 elements don't need sorting
9 if (len < 2) {
10 return arr
11 }
12
13 middle = Math.floor(len/2)
14
15 left = arr.slice(0, middle) // left side, from 0 to the middle
16 right = arr.slice(middle) // right side, from the middle to the end
17
18 return merge(MergeSort(left), MergeSort(right))
19
20 }

33. 33
1 // Merges 2 sorted arrays
2 function merge(left, right) {
3 let result = [],
4 i = 0,
5 j = 0
6
7 while(i < left.length && j < right.length) {
8
9 // Elements in both arrays are compared against each other.
10 // Whichever element is smaller it's inserted in the results.
11
12 // Each time a value from an array is added, it’s
13 // corresponding index variable is incremented.
14
15 if(left[i] < right[j]) {
16 result.push(left[i++])
17 } else {
18 result.push(right[j++])
19 }
20 }
21
22 // As soon as one of the arrays has been finished, the
23 // remaining values are added to the end of the result array
24
25 return result.concat(left.slice(i)).concat(right.slice(j))
26
27 }

34. @koste4
23 LOC

35. @koste4
QUICK SORT
Find a pivot
1
3
2 Partition the array so that
all items smaller than the
pivot item are to the left
and all items larger are to
the right
Sort the subarrays

36. @koste4
QUICK SORT

37. 37
1 // Find a "pivot" element in the array to compare all other
2 // elements against and then shift elements before or after
3 // pivot depending on their values
4 function QuickSort(arr, left = 0, right = arr.length - 1) {
5 let len = arr.length,
6 index
7
8 if(len > 1) {
9
10 index = partition(arr, left, right)
11
12 if(left < index - 1) {
13 QuickSort(arr, left, index - 1)
14 }
15
16 if(index < right) {
17 QuickSort(arr, index, right)
18 }
19
20 }
21
22 return arr
23
24 }

38. 38
1 function partition(arr, left, right) {
2 let middle = Math.floor((right + left) / 2),
3 pivot = arr[middle],
4 i = left, // Start pointer at the first item in the array
5 j = right // Start pointer at the last item in the array
6
7 while(i <= j) {
8 // Move left pointer to the right until the value at the
9 // left is greater than the pivot value
10 while(arr[i] < pivot) {
11 i++
12 }
13
14 // Move right pointer to the left until the value at the
15 // right is less than the pivot value
16 while(arr[j] > pivot) {
17 j--
18 }
19
20 // If the left pointer is less than or equal to the
21 // right pointer, then swap values
22 if(i <= j) {
23 [arr[i], arr[j]] = [arr[j], arr[i]] // ES6 destructuring swap
24 i++
25 j--
26 }
27 }
28
29 return i
30
31 }

39. @koste4
31 LOC

40. 1 Array.prototype.InsertSort = function() {
2 /* your implementation here */
3 }
4
5 Array.prototype.MergeSort = function() {
6 /* your implementation here */
7 }
8
9 Array.prototype.QuickSort = function() {
10 /* your implementation here */
11 }
12
13 myArray.InsertSort()
14 myArray.MergeSort()
15 myArray.QuickSort()

41. @koste4
WHY
SHOULD I
CARE?

42. @koste4
DESIGN
STRATEGIES

43. @koste4

44. @koste4
\$ git bisect start

45. @koste4
STABILITY

46. @koste4

47. const people = [
{ name: 'Faith Acet', age: 17 },
{ name: 'Armagan Amcalar', age: 42 },
{ name: 'Yaprak Ayazoglu', age: 26 },
{ name: 'Douglas Crockford', age: 26 },
{ name: 'Varya Dubinina', age: 11 },
{ name: 'Imad Elyafi', age: 26 },
{ name: 'Sebastian Golasch', age: 26 },
{ name: 'Diego González', age: 6 },
{ name: 'Claudia Hernández', age: 26 },
{ name: 'Asim Hussain', age: 26 },
{ name: 'Georg Neis', age: 12 },
{ name: 'Maxim Salnikov', age: 32 },
{ name: 'Isa Silveria', age: 32 },
{ name: 'André Staltz', age: 54 },
{ name: 'Jennifer Voss', age: 11 },
]

48. people.sort((a,b) => {
return a.age - b.age
}

49. @koste4
V8

50. [{ name: 'Diego González', age: 6 },
{ name: 'Jennifer Voss', age: 11 },
{ name: 'Varya Dubinina', age: 11 },
{ name: 'Georg Neis', age: 12 },
{ name: 'Faith Acet', age: 17 },
{ name: 'Imad Elyafi', age: 26 },
{ name: 'Sebastian Golasch', age: 26 },
{ name: 'Douglas Crockford', age: 26 },
{ name: 'Claudia Hernández', age: 26 },
{ name: 'Yaprak Ayazoglu', age: 26 },
{ name: 'Asim Hussain', age: 26 },
{ name: 'Maxim Salnikov', age: 32 },
{ name: 'Isa Silveira', age: 32 },
{ name: 'Armagan Amcalar', age: 42 },
{ name: 'André Staltz', age: 54 }]

51. @koste4
NITRO

52. [{ name: 'Diego González', age: 6 },
{ name: 'Jennifer Voss', age: 11 },
{ name: 'Varya Dubinina', age: 11 },
{ name: 'Georg Neis', age: 12 },
{ name: 'Faith Acet', age: 17 },
{ name: 'Yaprak Ayazoglu', age: 26 },
{ name: 'Douglas Crockford', age: 26 },
{ name: 'Imad Elyafi', age: 26 },
{ name: 'Sebastian Golasch', age: 26 },
{ name: 'Claudia Hernández', age: 26 },
{ name: 'Asim Hussain', age: 26 },
{ name: 'Maxim Salnikov', age: 32 },
{ name: 'Isa Silveira', age: 32 },
{ name: 'Armagan Amcalar', age: 42 },
{ name: 'André Staltz', age: 54 }]

53. @koste4
PERFORMANCE

54. 54
V 8 N I T R O

55. @koste4
SELF-HOSTING
Implementing parts of a
language in that very language
itself

56. @koste4
All these array methods take a callback
as an argument
Arrays in JS have methods like ,
_ , and of course
forEach
map reduce sort
BUT, BUT, SLOW...

57. @koste4
They iterate over the list and invoke the
callback for every element
Execution has to switch between compiled
C++ and interpreted JS
BUT, BUT, SLOW...

58. @koste4
Context switch is expensive
Staying in the same execution context and
within the same language allows us to have
BUT, BUT, SLOW...

59. @koste4
JS Engine Sort Algorithm Self-Host ?
SpiderMonkey
F I R E F O X
Insertion Sort
(for short arrays)
Merge Sort
No
V8
C H R O M E
Insertion Sort
(for short arrays)
Quick Sort
Yes
Nitro
S A FA R I
Merge Sort Yes
Chakra
I N T E R N E T E X P L O R E R
QuickSort No

60. @koste4
LET’S DO SOME
BENCHMARKING!

61. @koste4
10 ELEMENTS

62. @koste4
10O ELEMENTS

63. @koste4
1,0O0 ELEMENTS

64. @koste4
100,00O ELEMENTS

65. @koste4
1,000,000 ELEMENTS

66. @koste4
1,000,000 ELEMENTS

67. @koste4
10,000,000 ELEMENTS

68. 69
Claudia’s Sorting
Algorithms
Certification
ALL OF YOU
SORTING ALGORITHMS IN JS
AMSTERDAMJS 2018
01 JUN 2018
* Not a real certificate
*

69. @koste4
The Algorithm Design Manual
by Steven S. Skiena
Foundations of Algorithms
by Richard Neapolitan &