From a90f083be877c8534e5cb50af6a64a8ec45c8730 Mon Sep 17 00:00:00 2001 From: Abbe Keultjes Date: Sat, 20 Feb 2021 22:07:55 +0100 Subject: [PATCH] feat(grid): pass cursor along with hexes in getPrevHexState() for a ~20% performance increase When traversing a grid more than once the cursor was determined by doing a complete iteration of the previous traverser in order to get the last hex. The next traverser continues where the previous traverser left off. Now, the cursor is also returned when the previous traverser is called. This increases performance with ~20% when traversing a 10k hex grid twice. --- src/grid/grid.ts | 35 ++++++++++++++++++----------------- src/grid/types.ts | 9 +++++++-- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/grid/grid.ts b/src/grid/grid.ts index 8bdd6b88..ce0c566c 100644 --- a/src/grid/grid.ts +++ b/src/grid/grid.ts @@ -1,11 +1,11 @@ import { createHex, Hex, HexCoordinates } from '../hex' import { NoopMap } from './noopMap' import { rectangle, RectangleOptions } from './traversers' -import { eachCallbackFn, GetOrCreateHexFn, GetPrevHexesFn, GridStore, mapCallbackFn, Traverser } from './types' +import { eachCallbackFn, GetOrCreateHexFn, GetPrevHexState, GridStore, mapCallbackFn, Traverser } from './types' export class Grid { - static of(hexPrototype: T, store?: GridStore, getPrevHexes?: GetPrevHexesFn) { - return new Grid(hexPrototype, store, getPrevHexes) + static of(hexPrototype: T, store?: GridStore, getPrevHexState?: GetPrevHexState) { + return new Grid(hexPrototype, store, getPrevHexState) } getOrCreateHex: GetOrCreateHexFn = (coordinates) => { @@ -16,28 +16,28 @@ export class Grid { constructor( public hexPrototype: T, public store: GridStore = new NoopMap(), - private getPrevHexes: GetPrevHexesFn = () => [], + private getPrevHexState: GetPrevHexState = () => ({ hexes: [], cursor: null }), ) {} *[Symbol.iterator]() { - for (const hex of this.getPrevHexes()) { + for (const hex of this.getPrevHexState().hexes) { yield hex } } // it doesn't take a hexPrototype and store because it doesn't need to copy those - clone(getPrevHexes = this.getPrevHexes) { - // bind(this) in case the getPrevHexes is a "regular" (generator) function - return Grid.of(this.hexPrototype, this.store, getPrevHexes.bind(this)) + clone(getPrevHexState = this.getPrevHexState) { + // bind(this) in case the getPrevHexState is a "regular" (generator) function + return Grid.of(this.hexPrototype, this.store, getPrevHexState.bind(this)) } each(callback: eachCallbackFn) { const each = () => { - const prevHexes = this.getPrevHexes() - for (const hex of prevHexes) { + const prevHexState = this.getPrevHexState() + for (const hex of prevHexState.hexes) { callback(hex, this) } - return prevHexes + return prevHexState } return this.clone(each) @@ -45,11 +45,12 @@ export class Grid { map(callback: mapCallbackFn) { const map = () => { + const { hexes, cursor } = this.getPrevHexState() const nextHexes: T[] = [] - for (const hex of this.getPrevHexes()) { + for (const hex of hexes) { nextHexes.push(callback(hex, this)) } - return nextHexes + return { hexes: nextHexes, cursor } } return this.clone(map) @@ -57,7 +58,7 @@ export class Grid { // todo: alias to take or takeUntil? run(stopFn: (hex: T) => boolean = () => false) { - for (const hex of this.getPrevHexes()) { + for (const hex of this.getPrevHexState().hexes) { if (stopFn(hex)) { return this } @@ -78,9 +79,9 @@ export class Grid { return this } - const traverse: GetPrevHexesFn = () => { + const traverse: GetPrevHexState = () => { const nextHexes: T[] = [] - let cursor = Array.from(this.getPrevHexes()).pop() ?? createHex(this.hexPrototype).clone() // clone to enable users to make custom hexes + let cursor = this.getPrevHexState().cursor ?? createHex(this.hexPrototype).clone() // clone to enable users to make custom hexes for (const traverser of traversers) { for (const nextCursor of traverser(cursor, this.getOrCreateHex)) { @@ -89,7 +90,7 @@ export class Grid { } } - return nextHexes + return { hexes: nextHexes, cursor } } return this.clone(traverse) diff --git a/src/grid/types.ts b/src/grid/types.ts index 870473e4..db33b02d 100644 --- a/src/grid/types.ts +++ b/src/grid/types.ts @@ -1,8 +1,13 @@ import { Hex, HexCoordinates } from '../hex' import { Grid } from './grid' -export interface GetPrevHexesFn { - (this: Grid): Iterable +export interface PrevHexState { + hexes: Iterable + cursor: T | null +} + +export interface GetPrevHexState { + (this: Grid): PrevHexState } export interface Traverser {