mirror of
https://github.com/nasa/openmct.git
synced 2025-06-14 21:28:12 +00:00
[Telemetry] Remove linear search
Remove linear search for unused positions when queuing telemetry updates; instead, track available positions such that insertion is more performant at a modest cost (bound to the number of subscriptions) of retrieval. Additionally, add implementation notes in-line. WTD-1202.
This commit is contained in:
@ -35,28 +35,68 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function TelemetryQueue() {
|
function TelemetryQueue() {
|
||||||
var queue = [];
|
// General approach here:
|
||||||
|
// * Maintain a queue as an array of objects containing key-value
|
||||||
|
// pairs. Putting values into the queue will assign to the
|
||||||
|
// earliest-available queue position for the associated key
|
||||||
|
// (appending to the array if necessary.)
|
||||||
|
// * Maintain a set of counts for each key, such that determining
|
||||||
|
// the next available queue position is easy; O(1) insertion.
|
||||||
|
// * When retrieving objects, pop off the queue and decrement
|
||||||
|
// counts. This provides O(n+k) or O(k) retrieval for a queue
|
||||||
|
// of length n with k unique keys; this depends on whether
|
||||||
|
// the browser's implementation of Array.prototype.shift is
|
||||||
|
// O(n) or O(1).
|
||||||
|
|
||||||
|
// Graphically (indexes at top, keys along side, values as *'s),
|
||||||
|
// if we have a queue that looks like:
|
||||||
|
// 0 1 2 3 4
|
||||||
|
// a * * * * *
|
||||||
|
// b * *
|
||||||
|
// c * * *
|
||||||
|
//
|
||||||
|
// And we put a new value for b, we expect:
|
||||||
|
// 0 1 2 3 4
|
||||||
|
// a * * * * *
|
||||||
|
// b * * *
|
||||||
|
// c * * *
|
||||||
|
var queue = [],
|
||||||
|
counts = {};
|
||||||
|
|
||||||
// Look up an object in the queue that does not have a value
|
// Look up an object in the queue that does not have a value
|
||||||
// assigned to this key (or, add a new one)
|
// assigned to this key (or, add a new one)
|
||||||
function getFreeObject(key) {
|
function getFreeObject(key) {
|
||||||
var index = 0, object;
|
var index = counts[key] || 0, object;
|
||||||
|
|
||||||
// Look for an existing queue position where we can store
|
// Track the largest free position for this key
|
||||||
// a value to this key without overwriting an existing value.
|
counts[key] = index + 1;
|
||||||
for (index = 0; index < queue.length; index += 1) {
|
|
||||||
if (queue[index][key] === undefined) {
|
// If it's before the end of the queue, add it there
|
||||||
return queue[index];
|
if (index < queue.length) {
|
||||||
}
|
return queue[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we made it through the loop, values have been assigned
|
// Otherwise, values have been assigned
|
||||||
// to that key in all queued containers, so we need to queue
|
// to that key in all queued containers, so we need to queue
|
||||||
// up a new container for key-value pairs.
|
// up a new container for key-value pairs.
|
||||||
object = {};
|
object = {};
|
||||||
queue.push(object);
|
queue.push(object);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decrement counts for a specific key
|
||||||
|
function decrementCount(key) {
|
||||||
|
if (counts[key] < 2) {
|
||||||
|
delete counts[key];
|
||||||
|
} else {
|
||||||
|
counts[key] -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement all counts
|
||||||
|
function decrementCounts() {
|
||||||
|
Object.keys(counts).forEach(decrementCount);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
@ -74,6 +114,8 @@ define(
|
|||||||
* @return {object} key-value pairs
|
* @return {object} key-value pairs
|
||||||
*/
|
*/
|
||||||
poll: function () {
|
poll: function () {
|
||||||
|
// Decrement counts for the object that will be popped
|
||||||
|
decrementCounts();
|
||||||
return queue.shift();
|
return queue.shift();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user