PriorityQueue implementation for jest-worker#10921
Conversation
|
@MichaReiser @mjesun is this waiting for me? 😅 |
|
@SimenB would be great if you could take a look at it to get someone else's opinion on the changes and if this is something that would be beneficial for |
|
I assumed this was some FB thing that you needed and it'd go through without me having to do anything except publishing 😅 From skimming I think this looks good, especially as there's no change in default behavior. And the motivation for the new feature seems sound to me 👍 And of course the improved benchmarks you posted are awesome |
| queue.enqueue(createQueueChildMessage({priority})); | ||
| } | ||
|
|
||
| priorities.sort((a, b) => a - b); |
There was a problem hiding this comment.
| priorities.sort((a, b) => a - b); | |
| priorities.sort(); |
There was a problem hiding this comment.
The override is required because JavaScript does by default a lexicographical sort.
The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values. MDN
[10, 3, 4, 8, 2, 9, 7, 1, 2, 6, 5].sort()
Array(11) [ 1, 10, 2, 2, 3, 4, 5, 6, 7, 8, … ]
|
Thanks @SimenB for your thoughtful review!
It did start as part of some work on Metro but then turned out that switching to a priority queue does not improve the performance as much as we hoped for. I then decided to clean up the implementation because in my spare time because I believed the separation of concerns (extracting the task queue) is worth it and a priority queue might come in handy for someone else (or we might need it in the end). |
|
I resolved the conflicts of this PR and added the changelog entry. Should now be ready to merge. |
|
Thanks! |
|
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
The current
jest-workerimplementation processes tasks in FIFO ordering. This assumes that all tasks are equally important which isn't always given.This PR extracts a
TaskQueueinterface, extracts the existing implementation asFifoQueue, adds a newPriorityQueueimplementations and allows customizing the usedqueueimplementation when creating theJestWorker.A
TaskQueueoffers two operations:enqueue(workerId: ?number): Add a new task to the queue of the specified worker or for all workers if theworkerIdis absentdequeue(workerId: number): Return the next task to process for the specified worker id.The
PriorityQueueuses aMinHeapthat haslog(n)complexity forenqueueand O(1) complexity for the dequeue implementation. The implementation uses a shared and n worker specific queues to support sticky workers. The implementation returns the tasks in the ordering according to their priority. Tasks with equal priority are returned in any order except that sticky-tasks are returned before tasks queued in the shared queue.This diff extracts the current queue implementation into the
FifoQueueclass and refactors the implementation to reduce the memory footprint. The current implementation added non-worker specific tasks to the queue of each worker. The result is that there aren * tasksqueue entries wherenis the number of workers for shared tasks. Furthermore,dequeuingrequired to iterate through all tasks from the top until a task that hasn't been processed is found. The refactored implementation uses a shared queue and a separate queue for each worker. Shared tasks are only enqueued in the shared queue. Each task can only be part of one queue making it redundant to find the first non-processed task duringdequeue.Test plan
Unit tests for the new queue implementations. Existing integration tests pass with the refactored FIFO queue implementation.
Empty
FIFO Current
FIFO Refactored
loadTest
FIFO Current
FIFO Refactored