Merge pull request #2254 from google/connection-array

Speed up the connection DB
This commit is contained in:
Rachel Fenichel
2019-02-04 09:12:22 -08:00
committed by GitHub
2 changed files with 38 additions and 38 deletions

View File

@@ -36,15 +36,14 @@ goog.require('Blockly.Connection');
* @constructor
*/
Blockly.ConnectionDB = function() {
/**
* Array of connections sorted by y coordinate.
* @type {!Array.<!Blockly.Connection>}
* @private
*/
this.connections_ = [];
};
Blockly.ConnectionDB.prototype = new Array();
/**
* Don't inherit the constructor from Array.
* @type {!Function}
*/
Blockly.ConnectionDB.constructor = Blockly.ConnectionDB;
/**
* Add a connection to the database. Must not already exist in DB.
* @param {!Blockly.Connection} connection The connection to be added.
@@ -58,7 +57,7 @@ Blockly.ConnectionDB.prototype.addConnection = function(connection) {
return;
}
var position = this.findPositionForConnection_(connection);
this.splice(position, 0, connection);
this.connections_.splice(position, 0, connection);
connection.inDB_ = true;
};
@@ -71,12 +70,12 @@ Blockly.ConnectionDB.prototype.addConnection = function(connection) {
* not found.
*/
Blockly.ConnectionDB.prototype.findConnection = function(conn) {
if (!this.length) {
if (!this.connections_.length) {
return -1;
}
var bestGuess = this.findPositionForConnection_(conn);
if (bestGuess >= this.length) {
if (bestGuess >= this.connections_.length) {
// Not in list
return -1;
}
@@ -85,15 +84,16 @@ Blockly.ConnectionDB.prototype.findConnection = function(conn) {
// Walk forward and back on the y axis looking for the connection.
var pointerMin = bestGuess;
var pointerMax = bestGuess;
while (pointerMin >= 0 && this[pointerMin].y_ == yPos) {
if (this[pointerMin] == conn) {
while (pointerMin >= 0 && this.connections_[pointerMin].y_ == yPos) {
if (this.connections_[pointerMin] == conn) {
return pointerMin;
}
pointerMin--;
}
while (pointerMax < this.length && this[pointerMax].y_ == yPos) {
if (this[pointerMax] == conn) {
while (pointerMax < this.connections_.length &&
this.connections_[pointerMax].y_ == yPos) {
if (this.connections_[pointerMax] == conn) {
return pointerMax;
}
pointerMax++;
@@ -111,16 +111,16 @@ Blockly.ConnectionDB.prototype.findConnection = function(conn) {
*/
Blockly.ConnectionDB.prototype.findPositionForConnection_ = function(
connection) {
if (!this.length) {
if (!this.connections_.length) {
return 0;
}
var pointerMin = 0;
var pointerMax = this.length;
var pointerMax = this.connections_.length;
while (pointerMin < pointerMax) {
var pointerMid = Math.floor((pointerMin + pointerMax) / 2);
if (this[pointerMid].y_ < connection.y_) {
if (this.connections_[pointerMid].y_ < connection.y_) {
pointerMin = pointerMid + 1;
} else if (this[pointerMid].y_ > connection.y_) {
} else if (this.connections_[pointerMid].y_ > connection.y_) {
pointerMax = pointerMid;
} else {
pointerMin = pointerMid;
@@ -144,7 +144,7 @@ Blockly.ConnectionDB.prototype.removeConnection_ = function(connection) {
throw Error('Unable to find connection in connectionDB.');
}
connection.inDB_ = false;
this.splice(removalIndex, 1);
this.connections_.splice(removalIndex, 1);
};
/**
@@ -156,7 +156,7 @@ Blockly.ConnectionDB.prototype.removeConnection_ = function(connection) {
* @return {!Array.<Blockly.Connection>} List of connections.
*/
Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
var db = this;
var db = this.connections_;
var currentX = connection.x_;
var currentY = connection.y_;
@@ -218,7 +218,7 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
* @private
*/
Blockly.ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) {
return (Math.abs(this[index].y_ - baseY) <= maxRadius);
return (Math.abs(this.connections_[index].y_ - baseY) <= maxRadius);
};
/**
@@ -235,7 +235,7 @@ Blockly.ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) {
Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
dxy) {
// Don't bother.
if (!this.length) {
if (!this.connections_.length) {
return {connection: null, radius: maxRadius};
}
@@ -258,7 +258,7 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
// Walk forward and back on the y axis looking for the closest x,y point.
var pointerMin = closestIndex - 1;
while (pointerMin >= 0 && this.isInYRange_(pointerMin, conn.y_, maxRadius)) {
temp = this[pointerMin];
temp = this.connections_[pointerMin];
if (conn.isConnectionAllowed(temp, bestRadius)) {
bestConnection = temp;
bestRadius = temp.distanceFrom(conn);
@@ -267,9 +267,9 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
}
var pointerMax = closestIndex;
while (pointerMax < this.length && this.isInYRange_(pointerMax, conn.y_,
maxRadius)) {
temp = this[pointerMax];
while (pointerMax < this.connections_.length &&
this.isInYRange_(pointerMax, conn.y_, maxRadius)) {
temp = this.connections_[pointerMax];
if (conn.isConnectionAllowed(temp, bestRadius)) {
bestConnection = temp;
bestRadius = temp.distanceFrom(conn);

View File

@@ -20,10 +20,10 @@
'use strict';
function verify_DB_(msg, expected, db) {
var equal = (expected.length == db.length);
var equal = (expected.length == db.connections_.length);
if (equal) {
for (var i = 0; i < expected.length; i++) {
if (expected[i] != db[i]) {
if (expected[i] != db.connections_[i]) {
equal = false;
break;
}
@@ -32,7 +32,7 @@ function verify_DB_(msg, expected, db) {
if (equal) {
assertTrue(msg, true);
} else {
assertEquals(msg, expected, db);
assertEquals(msg, expected, db.connections_);
}
}
@@ -122,21 +122,21 @@ function test_DB_getNeighbours() {
var result = helper_getNeighbours(db, 0, 0, 4);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i]), -1); // contains
assertNotEquals(result.indexOf(db.connections_[i]), -1); // contains
}
// Test block belongs at middle.
result = helper_getNeighbours(db, 0, 4, 2);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i + 2]), -1); // contains
assertNotEquals(result.indexOf(db.connections_[i + 2]), -1); // contains
}
// Test block belongs at end.
result = helper_getNeighbours(db, 0, 9, 4);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i + 5]), -1); // contains
assertNotEquals(result.indexOf(db.connections_[i + 5]), -1); // contains
}
// Test block has no neighbours due to being out of range in the x direction.
@@ -165,7 +165,7 @@ function test_DB_findPositionForConnection() {
db.addConnection(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT,
null, true));
assertEquals(5, db.length);
assertEquals(5, db.connections_.length);
var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT, null,
true);
assertEquals(3, db.findPositionForConnection_(conn));
@@ -183,7 +183,7 @@ function test_DB_findConnection() {
var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null,
true);
db.addConnection(conn);
assertEquals(conn, db[db.findConnection(conn)]);
assertEquals(conn, db.connections_[db.findConnection(conn)]);
conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null, true);
assertEquals(-1, db.findConnection(conn));
@@ -197,7 +197,7 @@ function test_DB_ordering() {
}
for (i = 0; i < 10; i++) {
assertEquals(i, db[i].y_);
assertEquals(i, db.connections_[i].y_);
}
// quasi-random
@@ -221,7 +221,7 @@ function test_DB_ordering() {
}
for (i = 1; i < xCoords.length; i++) {
assertTrue(db[i].y_ >= db[i - 1].y_);
assertTrue(db.connections_[i].y_ >= db.connections_[i - 1].y_);
}
}
@@ -246,13 +246,13 @@ function test_SearchForClosest() {
}
// Should be at 0, 9.
var last = db[db.length - 1];
var last = db.connections_[db.connections_.length - 1];
// Correct connection is last in db; many connections in radius.
assertEquals(last, helper_searchDB(db, 0, 10, 15, sharedWorkspace));
// Nothing nearby.
assertEquals(null, helper_searchDB(db, 100, 100, 3, sharedWorkspace));
// First in db, exact match.
assertEquals(db[0], helper_searchDB(db, 0, 0, 0, sharedWorkspace));
assertEquals(db.connections_[0], helper_searchDB(db, 0, 0, 0, sharedWorkspace));
tempConn = helper_createConnection(6, 6, Blockly.PREVIOUS_STATEMENT,
sharedWorkspace, true);