diff --git a/Source/Core/RequestQueue.js b/Source/Core/RequestQueue.js
deleted file mode 100644
index 169483d3881c..000000000000
--- a/Source/Core/RequestQueue.js
+++ /dev/null
@@ -1,186 +0,0 @@
-define([
- './Check',
- './defineProperties'
- ], function(
- Check,
- defineProperties) {
- 'use strict';
-
- /**
- * Priority queue for the {@link RequestScheduler} implemented as a sorted array.
- * The request with the highest priority is placed at index 0 and the request
- * with lowest priority is placed at index length - 1
.
- *
- * A lower request.priority
value indicates that the request has higher priority. See {@link Request#priority}.
- *
length
number of requests from the top of the queue.
- *
- * @param {Number} length The number of requests to remove.
- */
- RequestQueue.prototype.remove = function(length) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.number.greaterThanOrEquals('length', length, 0);
- Check.typeOf.number.lessThanOrEquals('length', length, this._length);
- //>>includeEnd('debug');
- if (length === 0) {
- return;
- }
- if (length === this._length) {
- this._length = 0;
- return;
- }
-
- // Shift remaining requests back to the left
- var array = this._array;
- for (var i = length; i < this._length; ++i) {
- array[i - length] = array[i];
- }
- this._length -= length;
- };
-
- /**
- * The callback to use in forEach.
- * @callback RequestQueue~ForEachCallback
- * @param {Request} request The request.
- */
-
- return RequestQueue;
-});
diff --git a/Source/Core/RequestScheduler.js b/Source/Core/RequestScheduler.js
index 8c307663d3a4..6fd455b58007 100644
--- a/Source/Core/RequestScheduler.js
+++ b/Source/Core/RequestScheduler.js
@@ -6,9 +6,9 @@ define([
'./defined',
'./defineProperties',
'./Event',
+ './Heap',
'./isBlobUri',
'./isDataUri',
- './RequestQueue',
'./RequestState'
], function(
Uri,
@@ -18,12 +18,16 @@ define([
defined,
defineProperties,
Event,
+ Heap,
isBlobUri,
isDataUri,
- RequestQueue,
RequestState) {
'use strict';
+ function sortRequests(a, b) {
+ return a.priority - b.priority;
+ }
+
var statistics = {
numberOfAttemptedRequests : 0,
numberOfActiveRequests : 0,
@@ -33,8 +37,12 @@ define([
numberOfActiveRequestsEver : 0
};
- var requestQueueLength = 20;
- var requestQueue = new RequestQueue(requestQueueLength);
+ var priorityHeapLength = 20;
+ var requestHeap = new Heap({
+ comparator : sortRequests
+ });
+ requestHeap.maximumLength = priorityHeapLength;
+ requestHeap.reserve(priorityHeapLength);
var activeRequests = [];
var numberOfActiveRequestsByServer = {};
@@ -115,28 +123,29 @@ define([
},
/**
- * The maximum length of the request queue. This limits the number of requests that are sorted by priority. Only applies to requests that are not yet active.
+ * The maximum size of the priority heap. This limits the number of requests that are sorted by priority. Only applies to requests that are not yet active.
*
* @memberof RequestScheduler
*
* @type {Number}
* @default 20
- *
- * @private
*/
- requestQueueLength : {
+ priorityHeapLength : {
get : function() {
- return requestQueueLength;
+ return priorityHeapLength;
},
set : function(value) {
- // Cancel all requests and resize the queue
- var length = requestQueue.length;
- for (var i = 0; i < length; ++i) {
- var request = requestQueue.get(i);
- cancelRequest(request);
+ // If the new length shrinks the heap, need to cancel some of the requests.
+ // Since this value is not intended to be tweaked regularly it is fine to just cancel the high priority requests.
+ if (value < priorityHeapLength) {
+ while (requestHeap.length > value) {
+ var request = requestHeap.pop();
+ cancelRequest(request);
+ }
}
- requestQueue = new RequestQueue(value);
- RequestScheduler.requestQueue = requestQueue;
+ priorityHeapLength = value;
+ requestHeap.maximumLength = value;
+ requestHeap.reserve(value);
}
}
});
@@ -245,19 +254,21 @@ define([
}
activeRequests.length -= removeCount;
- // Update priority of issued requests and resort the queue
- requestQueue.forEach(updatePriority);
- requestQueue.sort();
+ // Update priority of issued requests and resort the heap
+ var issuedRequests = requestHeap.internalArray;
+ var issuedLength = requestHeap.length;
+ for (i = 0; i < issuedLength; ++i) {
+ updatePriority(issuedRequests[i]);
+ }
+ requestHeap.resort();
// Get the number of open slots and fill with the highest priority requests.
// Un-throttled requests are automatically added to activeRequests, so activeRequests.length may exceed maximumRequests
var openSlots = Math.max(RequestScheduler.maximumRequests - activeRequests.length, 0);
var filledSlots = 0;
- var processedRequests = 0;
- var totalRequests = requestQueue.length;
- while (filledSlots < openSlots && processedRequests < totalRequests) {
- // Loop until all open slots are filled or the queue becomes empty
- request = requestQueue.get(processedRequests++);
+ while (filledSlots < openSlots && requestHeap.length > 0) {
+ // Loop until all open slots are filled or the heap becomes empty
+ request = requestHeap.pop();
if (request.cancelled) {
// Request was explicitly cancelled
cancelRequest(request);
@@ -273,7 +284,6 @@ define([
startRequest(request);
++filledSlots;
}
- requestQueue.remove(processedRequests);
updateStatistics();
};
@@ -346,9 +356,10 @@ define([
return undefined;
}
- // Insert into the priority queue and see if a request was bumped off. If this request is the lowest priority it will be returned.
+ // Insert into the priority heap and see if a request was bumped off. If this request is the lowest
+ // priority it will be returned.
updatePriority(request);
- var removedRequest = requestQueue.insert(request);
+ var removedRequest = requestHeap.insert(request);
if (defined(removedRequest)) {
if (removedRequest === request) {
@@ -398,19 +409,12 @@ define([
* @private
*/
RequestScheduler.clearForSpecs = function() {
- var request;
- var length;
- var i;
-
- length = requestQueue.length;
- for (i = 0; i < length; ++i) {
- request = requestQueue.get(i);
+ while (requestHeap.length > 0) {
+ var request = requestHeap.pop();
cancelRequest(request);
}
- requestQueue.remove(length);
-
- length = activeRequests.length;
- for (i = 0; i < length; ++i) {
+ var length = activeRequests.length;
+ for (var i = 0; i < length; ++i) {
cancelRequest(activeRequests[i]);
}
activeRequests.length = 0;
@@ -439,7 +443,7 @@ define([
*
* @private
*/
- RequestScheduler.requestQueue = requestQueue;
+ RequestScheduler.requestHeap = requestHeap;
return RequestScheduler;
});
diff --git a/Source/Scene/GlobeSurfaceTile.js b/Source/Scene/GlobeSurfaceTile.js
index efa1ab9f40bd..46bba1be5100 100644
--- a/Source/Scene/GlobeSurfaceTile.js
+++ b/Source/Scene/GlobeSurfaceTile.js
@@ -7,7 +7,6 @@ define([
'../Core/defineProperties',
'../Core/IntersectionTests',
'../Core/PixelFormat',
- '../Core/Rectangle',
'../Renderer/PixelDatatype',
'../Renderer/Sampler',
'../Renderer/Texture',
@@ -29,7 +28,6 @@ define([
defineProperties,
IntersectionTests,
PixelFormat,
- Rectangle,
PixelDatatype,
Sampler,
Texture,
@@ -256,10 +254,6 @@ define([
function createPriorityFunction(surfaceTile, frameState) {
return function() {
- if (Rectangle.contains(surfaceTile.tileBoundingRegion.rectangle, frameState.camera.positionCartographic)) {
- // If the camera is inside this tile's bounding region treat it as highest priority
- return 0.0;
- }
return surfaceTile.tileBoundingRegion.distanceToCamera(frameState);
};
}
diff --git a/Specs/Core/RequestQueueSpec.js b/Specs/Core/RequestQueueSpec.js
deleted file mode 100644
index a7bb51107e7e..000000000000
--- a/Specs/Core/RequestQueueSpec.js
+++ /dev/null
@@ -1,189 +0,0 @@
-defineSuite([
- 'Core/RequestQueue',
- 'Core/Math',
- 'Core/Request'
- ], function(
- RequestQueue,
- CesiumMath,
- Request) {
- 'use strict';
-
- var length = 20;
-
- function createRequest(distance) {
- return new Request({
- priority : distance
- });
- }
-
- function isSorted(queue) {
- var distance = Number.NEGATIVE_INFINITY;
- for (var i = 0; i < queue.length; ++i) {
- var requestDistance = queue.get(i).priority;
- if (requestDistance < distance) {
- return false;
- }
-
- distance = requestDistance;
- }
- return true;
- }
-
- it('sets initial values', function() {
- var queue = new RequestQueue(length);
- expect(queue._array.length).toBe(length);
- expect(queue._length).toBe(0);
- expect(queue._maximumLength).toBe(length);
- });
-
- it('gets length', function() {
- var queue = new RequestQueue(length);
- expect(queue.length).toBe(0);
- queue.insert(createRequest(1.0));
- expect(queue.length).toBe(1);
- });
-
- it('get', function() {
- var queue = new RequestQueue(length);
- queue.insert(createRequest(1));
- queue.insert(createRequest(0));
- expect(queue.get(0).priority).toBe(0);
- expect(queue.get(1).priority).toBe(1);
- });
-
- it('insert', function() {
- var removedRequest;
- var request;
- var i;
-
- CesiumMath.setRandomNumberSeed(0.0);
- var distances = new Array(length);
- for (i = 0; i < length; ++i) {
- distances[i] = CesiumMath.nextRandomNumber();
- }
- distances.sort();
- var lowestDistance = distances[0];
- var highestDistance = distances[distances.length - 1];
-
- var queue = new RequestQueue(length);
- for (i = 0; i < length; ++i) {
- removedRequest = queue.insert(createRequest(distances[i]));
- expect(removedRequest).toBeUndefined(); // Requests are not removed until the queue is full
- }
-
- expect(isSorted(queue)).toBe(true);
-
- request = createRequest(highestDistance);
- expect(queue.insert(request)).toBe(request);
-
- request = createRequest(highestDistance + 1.0);
- expect(queue.insert(request)).toBe(request);
-
- request = createRequest(lowestDistance);
- expect(queue.insert(request).priority).toBe(highestDistance);
- expect(queue.get(0).priority).toBe(lowestDistance);
- expect(queue.get(1).priority).toBe(lowestDistance);
- expect(queue.get(2).priority).toBeGreaterThan(lowestDistance);
-
- expect(isSorted(queue)).toBe(true);
- });
-
- it('forEach', function() {
- var total = 0;
- var queue = new RequestQueue(length);
- for (var i = 0; i < length; ++i) {
- queue.insert(createRequest(1));
- }
- queue.forEach(function(request) {
- total += request.priority;
- });
- expect(total).toBe(length);
- });
-
- it('sort', function() {
- var i;
- CesiumMath.setRandomNumberSeed(0.0);
- var queue = new RequestQueue(length);
- for (i = 0; i < length / 2; ++i) {
- queue.insert(createRequest(CesiumMath.nextRandomNumber()));
- }
- queue.forEach(function(request) {
- request.priority = CesiumMath.nextRandomNumber();
- });
- expect(isSorted(queue)).toBe(false);
- queue.sort();
- expect(isSorted(queue)).toBe(true);
- });
-
- it('remove', function() {
- var queue = new RequestQueue(length);
- for (var i = 0; i < length; ++i) {
- queue.insert(createRequest(i));
- }
- queue.remove(0);
- expect(queue.get(0).priority).toBe(0);
- expect(queue.get(1).priority).toBe(1);
- expect(queue.length).toBe(length);
-
- queue.remove(1);
- expect(queue.get(0).priority).toBe(1);
- expect(queue.get(1).priority).toBe(2);
- expect(queue.length).toBe(length - 1);
-
- queue.remove(2);
- expect(queue.get(0).priority).toBe(3);
- expect(queue.get(1).priority).toBe(4);
- expect(queue.length).toBe(length - 3);
-
- queue.remove(17);
- expect(queue.length).toBe(0);
- });
-
- it('throws if maximumLength is undefined', function() {
- expect(function() {
- return new RequestQueue();
- }).toThrowDeveloperError();
- });
-
- it('throws if get index is out of range', function() {
- expect(function() {
- var queue = new RequestQueue(length);
- queue.get(0);
- }).toThrowDeveloperError();
-
- expect(function() {
- var queue = new RequestQueue(length);
- queue.insert(createRequest(0.0));
- queue.get(1);
- }).toThrowDeveloperError();
-
- expect(function() {
- var queue = new RequestQueue(length);
- queue.insert(createRequest(0.0));
- queue.get(-1);
- }).toThrowDeveloperError();
- });
-
- it('throws if forEach callback is not a function', function() {
- expect(function() {
- var queue = new RequestQueue(length);
- queue.forEach();
- }).toThrowDeveloperError();
- expect(function() {
- var queue = new RequestQueue(length);
- queue.forEach(5);
- }).toThrowDeveloperError();
- });
-
- it('throws if remove length is out of range', function() {
- expect(function() {
- var queue = new RequestQueue(length);
- queue.remove(1);
- }).toThrowDeveloperError();
-
- expect(function() {
- var queue = new RequestQueue(length);
- queue.remove(-1);
- }).toThrowDeveloperError();
- });
-});
diff --git a/Specs/Core/RequestSchedulerSpec.js b/Specs/Core/RequestSchedulerSpec.js
index b5b3b965cc16..55f49fc1492e 100644
--- a/Specs/Core/RequestSchedulerSpec.js
+++ b/Specs/Core/RequestSchedulerSpec.js
@@ -12,13 +12,13 @@ defineSuite([
var originalMaximumRequests;
var originalMaximumRequestsPerServer;
- var originalRequestQueueLength;
+ var originalPriorityHeapLength;
var originalRequestsByServer;
beforeAll(function() {
originalMaximumRequests = RequestScheduler.maximumRequests;
originalMaximumRequestsPerServer = RequestScheduler.maximumRequestsPerServer;
- originalRequestQueueLength = RequestScheduler.requestQueueLength;
+ originalPriorityHeapLength = RequestScheduler.priorityHeapLength;
originalRequestsByServer = RequestScheduler.requestsByServer;
});
@@ -30,7 +30,7 @@ defineSuite([
afterEach(function() {
RequestScheduler.maximumRequests = originalMaximumRequests;
RequestScheduler.maximumRequestsPerServer = originalMaximumRequestsPerServer;
- RequestScheduler.requestQueueLength = originalRequestQueueLength;
+ RequestScheduler.priorityHeapLength = originalPriorityHeapLength;
RequestScheduler.requestsByServer = originalRequestsByServer;
});
@@ -208,7 +208,7 @@ defineSuite([
}
});
- it('honors requestQueue length', function() {
+ it('honors priorityHeapLength', function() {
var deferreds = [];
var requests = [];
@@ -229,23 +229,22 @@ defineSuite([
return request;
}
- RequestScheduler.requestQueueLength = 1;
+ RequestScheduler.priorityHeapLength = 1;
var firstRequest = createRequest(0.0);
var promise = RequestScheduler.request(firstRequest);
expect(promise).toBeDefined();
promise = RequestScheduler.request(createRequest(1.0));
expect(promise).toBeUndefined();
- RequestScheduler.requestQueueLength = 3;
- promise = RequestScheduler.request(createRequest(1.0));
+ RequestScheduler.priorityHeapLength = 3;
promise = RequestScheduler.request(createRequest(2.0));
promise = RequestScheduler.request(createRequest(3.0));
expect(promise).toBeDefined();
promise = RequestScheduler.request(createRequest(4.0));
expect(promise).toBeUndefined();
- // The requests are cancelled when the queue length changes
- RequestScheduler.requestQueueLength = 2;
+ // A request is cancelled to accommodate the new heap length
+ RequestScheduler.priorityHeapLength = 2;
expect(firstRequest.state).toBe(RequestState.CANCELLED);
var length = deferreds.length;
@@ -453,7 +452,7 @@ defineSuite([
});
}
- var length = RequestScheduler.requestQueueLength;
+ var length = RequestScheduler.priorityHeapLength;
for (var i = 0; i < length; ++i) {
var priority = Math.random();
RequestScheduler.request(createRequest(priority));
@@ -490,7 +489,7 @@ defineSuite([
var i;
var request;
- var length = RequestScheduler.requestQueueLength;
+ var length = RequestScheduler.priorityHeapLength;
for (i = 0; i < length; ++i) {
var priority = i / (length - 1);
request = createRequest(priority);
@@ -502,31 +501,28 @@ defineSuite([
RequestScheduler.maximumRequests = 0;
RequestScheduler.update();
- var requestQueue = RequestScheduler.requestQueue;
+ var requestHeap = RequestScheduler.requestHeap;
var requests = [];
var currentTestId = 0;
-
- for (i = 0; i < length; ++i) {
- request = requestQueue.get(i);
+ while (requestHeap.length > 0) {
+ request = requestHeap.pop();
requests.push(request);
expect(request.testId).toBeGreaterThanOrEqualTo(currentTestId);
currentTestId = request.testId;
}
- requestQueue.remove(length);
for (i = 0; i < length; ++i) {
- requestQueue.insert(requests[i]);
+ requestHeap.insert(requests[i]);
}
invertPriority = true;
RequestScheduler.update();
- for (i = 0; i < length; ++i) {
- request = requestQueue.get(i);
+ while (requestHeap.length > 0) {
+ request = requestHeap.pop();
expect(request.testId).toBeLessThanOrEqualTo(currentTestId);
currentTestId = request.testId;
}
- requestQueue.remove(length);
});
it('handles low priority requests', function() {
@@ -547,7 +543,7 @@ defineSuite([
var mediumPriority = 0.5;
var lowPriority = 1.0;
- var length = RequestScheduler.requestQueueLength;
+ var length = RequestScheduler.priorityHeapLength;
for (var i = 0; i < length; ++i) {
RequestScheduler.request(createRequest(mediumPriority));
}