Skip to content

Commit

Permalink
feat(grid): pass cursor along with hexes in getPrevHexState() for a ~…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
flauwekeul committed Apr 22, 2021
1 parent 99192b2 commit a90f083
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 19 deletions.
35 changes: 18 additions & 17 deletions src/grid/grid.ts
Original file line number Diff line number Diff line change
@@ -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<T extends Hex> {
static of<T extends Hex>(hexPrototype: T, store?: GridStore<T>, getPrevHexes?: GetPrevHexesFn<T>) {
return new Grid<T>(hexPrototype, store, getPrevHexes)
static of<T extends Hex>(hexPrototype: T, store?: GridStore<T>, getPrevHexState?: GetPrevHexState<T>) {
return new Grid<T>(hexPrototype, store, getPrevHexState)
}

getOrCreateHex: GetOrCreateHexFn<T> = (coordinates) => {
Expand All @@ -16,48 +16,49 @@ export class Grid<T extends Hex> {
constructor(
public hexPrototype: T,
public store: GridStore<T> = new NoopMap(),
private getPrevHexes: GetPrevHexesFn<T> = () => [],
private getPrevHexState: GetPrevHexState<T> = () => ({ 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<T>) {
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)
}

map(callback: mapCallbackFn<T>) {
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)
}

// 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
}
Expand All @@ -78,9 +79,9 @@ export class Grid<T extends Hex> {
return this
}

const traverse: GetPrevHexesFn<T> = () => {
const traverse: GetPrevHexState<T> = () => {
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)) {
Expand All @@ -89,7 +90,7 @@ export class Grid<T extends Hex> {
}
}

return nextHexes
return { hexes: nextHexes, cursor }
}

return this.clone(traverse)
Expand Down
9 changes: 7 additions & 2 deletions src/grid/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Hex, HexCoordinates } from '../hex'
import { Grid } from './grid'

export interface GetPrevHexesFn<T extends Hex> {
(this: Grid<T>): Iterable<T>
export interface PrevHexState<T extends Hex> {
hexes: Iterable<T>
cursor: T | null
}

export interface GetPrevHexState<T extends Hex> {
(this: Grid<T>): PrevHexState<T>
}

export interface Traverser<T extends Hex> {
Expand Down

0 comments on commit a90f083

Please sign in to comment.