Skip to content

Commit

Permalink
Merge pull request #945 from lifeart/keyed-list-mutations-counter-test
Browse files Browse the repository at this point in the history
feat:  performance improvements for keyed lists changes
  • Loading branch information
wycats committed Jun 14, 2019
2 parents 0fb6a36 + 64fd0db commit cad7655
Show file tree
Hide file tree
Showing 2 changed files with 392 additions and 18 deletions.
66 changes: 48 additions & 18 deletions packages/@glimmer/reference/lib/iterable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LinkedList, ListNode, Option, expect } from '@glimmer/util';
import { LinkedList, ListNode, Option } from '@glimmer/util';
import { VersionedPathReference as PathReference, Tag } from './validators';

export interface IterationItem<T, U> {
Expand Down Expand Up @@ -115,6 +115,16 @@ export class IterationArtifacts {
return iterator;
}

advanceToKey(key: unknown, current: ListItem): Option<ListItem> {
let seek = current;

while (seek !== null && seek.key !== key) {
seek = this.advanceNode(seek);
}

return seek;
}

has(key: unknown): boolean {
return this.map.has(key);
}
Expand All @@ -128,6 +138,12 @@ export class IterationArtifacts {
return node !== undefined && node.seen;
}

update(item: OpaqueIterationItem): ListItem {
let found = this.get(item.key);
found.update(item);
return found;
}

append(item: OpaqueIterationItem): ListItem {
let { map, list, iterable } = this;

Expand All @@ -150,7 +166,6 @@ export class IterationArtifacts {

move(item: ListItem, reference: Option<ListItem>): void {
let { list } = this;

item.retained = true;
list.remove(item);
list.insertBefore(item, reference);
Expand All @@ -167,6 +182,11 @@ export class IterationArtifacts {
return this.list.nextNode(item);
}

advanceNode(item: ListItem): ListItem {
item.seen = true;
return this.list.nextNode(item);
}

head(): Option<ListItem> {
return this.list.head();
}
Expand Down Expand Up @@ -266,15 +286,27 @@ export class IteratorSynchronizer<Env> {
private advanceToKey(key: unknown) {
let { current, artifacts } = this;

let seek = current;
if (current === null) return;

while (seek !== null && seek.key !== key) {
seek.seen = true;
seek = artifacts.nextNode(seek);
let next = artifacts.advanceNode(current);

if (next.key === key) {
this.current = artifacts.advanceNode(next);
return;
}

let seek = artifacts.advanceToKey(key, current);

if (seek) {
this.move(seek, current);
this.current = artifacts.nextNode(current);
}
}

if (seek !== null) {
this.current = artifacts.nextNode(seek);
private move(item: ListItem, reference: Option<ListItem>) {
if (item.next !== reference) {
this.artifacts.move(item, reference);
this.target.move(this.env, item.key, item.value, item.memo, reference ? reference.key : END);
}
}

Expand All @@ -290,7 +322,7 @@ export class IteratorSynchronizer<Env> {
let { key } = item;

if (current !== null && current.key === key) {
this.nextRetain(item);
this.nextRetain(item, current);
} else if (artifacts.has(key)) {
this.nextMove(item);
} else {
Expand All @@ -300,26 +332,24 @@ export class IteratorSynchronizer<Env> {
return Phase.Append;
}

private nextRetain(item: OpaqueIterationItem) {
let { artifacts, current } = this;
private nextRetain(item: OpaqueIterationItem, current: ListItem) {
let { artifacts } = this;

current = expect(current, 'BUG: current is empty');
// current = expect(current, 'BUG: current is empty');

current.update(item);
this.current = artifacts.nextNode(current);
this.target.retain(this.env, item.key, current.value, current.memo);
}

private nextMove(item: OpaqueIterationItem) {
let { current, artifacts, target } = this;
let { current, artifacts } = this;
let { key } = item;

let found = artifacts.get(item.key);
found.update(item);
let found = artifacts.update(item);

if (artifacts.wasSeen(item.key)) {
artifacts.move(found, current);
target.move(this.env, found.key, found.value, found.memo, current ? current.key : END);
if (artifacts.wasSeen(key)) {
this.move(found, current);
} else {
this.advanceToKey(key);
}
Expand Down
Loading

0 comments on commit cad7655

Please sign in to comment.