Skip to content

Commit

Permalink
Improve performance of collection methods for unsorted state adapter
Browse files Browse the repository at this point in the history
These methods ran in quadratic time by interating over
the collection and applying a linear algorithm for each item.

Now, we modify entity hashes first (each in constant time),
and then update the array of their ids in linear time.

As a result, all operations now occur linearly.

We also simplified logic for single-item operations
by expressing them through those for collections.

The removal methods also apply to sorted collections
(because they preserve their order).
  • Loading branch information
Denis Loginov committed Sep 29, 2017
1 parent ee9067c commit 8dcb54c
Showing 1 changed file with 25 additions and 21 deletions.
46 changes: 25 additions & 21 deletions modules/entity/src/unsorted_state_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,17 @@ export function createUnsortedStateAdapter<T>(
}

function removeOneMutably(key: string, state: R): boolean {
const index = state.ids.indexOf(key);

if (index === -1) {
return false;
}

state.ids.splice(index, 1);
delete state.entities[key];

return true;
return removeManyMutably([key], state);
}

function removeManyMutably(keys: string[], state: R): boolean {
let didMutate = false;
const didMutate =
keys
.filter(key => key in state.entities)
.map(key => delete state.entities[key]).length > 0;

for (let index in keys) {
didMutate = removeOneMutably(keys[index], state) || didMutate;
if (didMutate) {
state.ids = state.ids.filter(id => id in state.entities);
}

return didMutate;
Expand All @@ -68,10 +62,12 @@ export function createUnsortedStateAdapter<T>(
});
}

function updateOneMutably(update: Update<T>, state: R): boolean {
const index = state.ids.indexOf(update.id);

if (index === -1) {
function takeNewKey(
keys: { [id: string]: string },
update: Update<T>,
state: R
): boolean {
if (!(update.id in state.entities)) {
return false;
}

Expand All @@ -80,7 +76,7 @@ export function createUnsortedStateAdapter<T>(
const newKey = selectId(updated);

if (newKey !== update.id) {
state.ids[index] = newKey;
keys[update.id] = newKey;
delete state.entities[update.id];
}

Expand All @@ -89,11 +85,19 @@ export function createUnsortedStateAdapter<T>(
return true;
}

function updateOneMutably(update: Update<T>, state: R): boolean {
return updateManyMutably([update], state);
}

function updateManyMutably(updates: Update<T>[], state: R): boolean {
let didMutate = false;
const newKeys: { [id: string]: string } = {};

const didMutate = updates
.map(update => takeNewKey(newKeys, update, state))
.includes(true);

for (let index in updates) {
didMutate = updateOneMutably(updates[index], state) || didMutate;
if (didMutate) {
state.ids = state.ids.map(id => newKeys[id] || id);
}

return didMutate;
Expand Down

0 comments on commit 8dcb54c

Please sign in to comment.