1 import { randomInt } from 'node:crypto'
3 import { bench, group, run } from 'tatami-ng'
5 function generateRandomTasksMap (
7 maxNumberOfTasksPerWorker = 10
10 for (let i = 0; i < numberOfWorkers; i++) {
11 const task = [i, randomInt(maxNumberOfTasksPerWorker)]
14 return new Map(tasksArray)
17 const tasksMap = generateRandomTasksMap(60, 20)
19 function loopSelect (tasksMap) {
21 let minValue = Infinity
22 for (const [key, value] of tasksMap) {
25 } else if (value < minValue) {
30 return [minKey, minValue]
33 function arraySortSelect (tasksMap) {
34 const tasksArray = Array.from(tasksMap)
35 return tasksArray.sort((a, b) => {
38 } else if (a[1] > b[1]) {
45 const defaultComparator = (a, b) => {
49 const defaultPivotIndexSelect = (leftIndex, rightIndex) => {
50 return leftIndex + Math.floor((rightIndex - leftIndex) / 2)
53 const randomPivotIndexSelect = (leftIndex, rightIndex) => {
54 return randomInt(leftIndex, rightIndex)
57 function swap (array, index1, index2) {
58 const tmp = array[index1]
59 array[index1] = array[index2]
68 compare = defaultComparator
70 const pivotValue = array[pivotIndex]
71 swap(array, pivotIndex, rightIndex)
72 let storeIndex = leftIndex
73 for (let i = leftIndex; i < rightIndex; i++) {
74 if (compare(array[i], pivotValue)) {
75 swap(array, storeIndex, i)
79 swap(array, rightIndex, storeIndex)
88 compare = defaultComparator,
89 pivotIndexSelect = defaultPivotIndexSelect
92 if (leftIndex === rightIndex) return array[leftIndex]
93 let pivotIndex = pivotIndexSelect(leftIndex, rightIndex)
94 pivotIndex = partition(array, leftIndex, rightIndex, pivotIndex, compare)
95 if (k === pivotIndex) {
97 } else if (k < pivotIndex) {
98 rightIndex = pivotIndex - 1
100 leftIndex = pivotIndex + 1
105 function selectRecursion (
110 compare = defaultComparator,
111 pivotIndexSelect = defaultPivotIndexSelect
113 if (leftIndex === rightIndex) return array[leftIndex]
114 let pivotIndex = pivotIndexSelect(leftIndex, rightIndex)
115 pivotIndex = partition(array, leftIndex, rightIndex, pivotIndex, compare)
116 if (k === pivotIndex) {
118 } else if (k < pivotIndex) {
119 return selectRecursion(array, k, leftIndex, pivotIndex - 1, compare)
121 return selectRecursion(array, k, pivotIndex + 1, rightIndex, k, compare)
125 function quickSelectLoop (tasksMap) {
126 const tasksArray = Array.from(tasksMap)
128 return selectLoop(tasksArray, 0, 0, tasksArray.length - 1, (a, b) => {
133 function quickSelectLoopRandomPivot (tasksMap) {
134 const tasksArray = Array.from(tasksMap)
140 tasksArray.length - 1,
144 randomPivotIndexSelect
148 function quickSelectRecursion (tasksMap) {
149 const tasksArray = Array.from(tasksMap)
151 return selectRecursion(tasksArray, 0, 0, tasksArray.length - 1, (a, b) => {
156 function quickSelectRecursionRandomPivot (tasksMap) {
157 const tasksArray = Array.from(tasksMap)
159 return selectRecursion(
163 tasksArray.length - 1,
167 randomPivotIndexSelect
171 group('Least used worker tasks distribution', () => {
172 bench('Loop select', () => {
175 bench('Array sort select', () => {
176 arraySortSelect(tasksMap)
178 bench('Quick select loop', () => {
179 quickSelectLoop(tasksMap)
181 bench('Quick select loop with random pivot', () => {
182 quickSelectLoopRandomPivot(tasksMap)
184 bench('Quick select recursion', () => {
185 quickSelectRecursion(tasksMap)
187 bench('Quick select recursion with random pivot', () => {
188 quickSelectRecursionRandomPivot(tasksMap)
192 await run({ units: true })