Speed up single-line deltas

2e6f12725b slowed down the application of
deltas that only affect a single line. The slow-down, though trivial for
a single line, is significant for operations than separately modify
thousands of rows (such as indenting a large document).

This commit speeds up single-line deltas by avoiding unnecessary calls
to splitLine() and joinLineWithNext().
This commit is contained in:
aldendaniels 2014-01-01 14:45:54 -06:00
commit 612478e39f

View file

@ -261,9 +261,13 @@ var Document = function(textOrLines) {
throw errorText;
}
// Validate action.
if (delta.action != 'insert' && delta.action != 'delete')
fnThrow('Delta action must be "insert" or "delete".');
// Validate lines.
if (!delta.lines instanceof Array)
fnThrow('Delta object lines must be an array');
fnThrow('Delta lines must be an array');
// Validate range type.
if (!delta.range instanceof Range)
@ -567,30 +571,50 @@ var Document = function(textOrLines) {
this.$validateDelta(delta);
// Apply delta.
switch (delta.action)
if (delta.range.start.row == delta.range.end.row)
{
case 'insert':
splitLine(this.$lines, delta.range.start);
for (var i = 0; i < delta.lines.length; i++) {
var row = delta.range.start.row + 1 + i;
this.$lines.splice(row, 0, delta.lines[i]);
}
joinLineWithNext(this.$lines, delta.range.start.row);
joinLineWithNext(this.$lines, delta.range.end.row);
break;
// Apply single-line delta.
// Note: The multi-line code below correctly handle single-line
// deltas too, but we need to short-circuit for speed.
var row = delta.range.start.row;
var startColumn = delta.range.start.column;
var endColumn = delta.range.end.column;
var line = this.$lines[row];
switch (delta.action) {
case 'insert':
this.$lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
break;
case 'delete':
this.$lines[row] = line.substring(0, startColumn) + line.substring(endColumn);
break;
}
} else {
case 'delete':
splitLine(this.$lines, delta.range.end);
splitLine(this.$lines, delta.range.start);
this.$lines.splice(
delta.range.start.row + 1, // Where to start deleting
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
);
joinLineWithNext(this.$lines, delta.range.start.row);
break;
default:
throw 'Invalid delta type: ' + delta.action
// Apply multi-line delta.
switch (delta.action) {
case 'insert':
splitLine(this.$lines, delta.range.start);
for (var i = 0; i < delta.lines.length; i++) {
var row = delta.range.start.row + 1 + i;
this.$lines.splice(row, 0, delta.lines[i]);
}
joinLineWithNext(this.$lines, delta.range.start.row);
joinLineWithNext(this.$lines, delta.range.end.row);
break;
case 'delete':
splitLine(this.$lines, delta.range.end);
splitLine(this.$lines, delta.range.start);
this.$lines.splice(
delta.range.start.row + 1, // Where to start deleting
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
);
joinLineWithNext(this.$lines, delta.range.start.row);
break;
}
}
this._emit("change", { data: delta });