Implement a basic benchmark test, and deprecate derivation.map()/flatMap()

This starts a new workspace at `packages/benchmarks` where future benchmarks
are going to sit. For now, it only contains a basic profile of a `sequence.play()`
setup.

It also removes all uses of `AbstractDerivation.map()/flatMap()` and uses prisms
instead.
This commit is contained in:
Aria Minaei 2022-11-26 15:00:14 +01:00
parent 45b548660c
commit ae8be59366
26 changed files with 37584 additions and 56 deletions

View file

@ -12,9 +12,9 @@ import type {PointerType} from '@theatre/dataverse'
import {isPointer} from '@theatre/dataverse'
import {isDerivation, valueDerivation} from '@theatre/dataverse'
import type {$IntentionalAny, VoidFn} from '@theatre/shared/utils/types'
import coreTicker from './coreTicker'
import type {ProjectId} from '@theatre/shared/utils/ids'
import {_coreLogger} from './_coreLogger'
import {getCoreTicker} from './coreTicker'
export {notify} from '@theatre/shared/notify'
export {types}
@ -156,9 +156,9 @@ export function onChange<P extends PointerType<$IntentionalAny>>(
): VoidFn {
if (isPointer(pointer)) {
const derivation = valueDerivation(pointer)
return derivation.tapImmediate(coreTicker, callback as $IntentionalAny)
return derivation.tapImmediate(getCoreTicker(), callback as $IntentionalAny)
} else if (isDerivation(pointer)) {
return pointer.tapImmediate(coreTicker, callback as $IntentionalAny)
return pointer.tapImmediate(getCoreTicker(), callback as $IntentionalAny)
} else {
throw new Error(
`Called onChange(p) where p is neither a pointer nor a derivation.`,

View file

@ -1,5 +1,17 @@
import {Ticker} from '@theatre/dataverse'
const coreTicker = Ticker.raf
let coreTicker: Ticker
export default coreTicker
export function setCoreTicker(ticker: Ticker) {
if (coreTicker) {
throw new Error(`coreTicker is already set`)
}
coreTicker = ticker
}
export function getCoreTicker(): Ticker {
if (!coreTicker) {
coreTicker = Ticker.raf
}
return coreTicker
}

View file

@ -1,12 +1,11 @@
import type Project from '@theatre/core/projects/Project'
import coreTicker from '@theatre/core/coreTicker'
import type Sheet from '@theatre/core/sheets/Sheet'
import type {SequenceAddress} from '@theatre/shared/utils/addresses'
import didYouMean from '@theatre/shared/utils/didYouMean'
import {InvalidArgumentError} from '@theatre/shared/utils/errors'
import type {IBox, IDerivation, Pointer} from '@theatre/dataverse'
import {pointer} from '@theatre/dataverse'
import {Box, prism, val, valueDerivation} from '@theatre/dataverse'
import {Box, prism, val} from '@theatre/dataverse'
import {padStart} from 'lodash-es'
import type {
IPlaybackController,
@ -17,6 +16,7 @@ import TheatreSequence from './TheatreSequence'
import type {ILogger} from '@theatre/shared/logger'
import type {ISequence} from '..'
import {notify} from '@theatre/shared/notify'
import {getCoreTicker} from '@theatre/core/coreTicker'
export type IPlaybackRange = [from: number, to: number]
@ -63,20 +63,22 @@ export default class Sequence {
this.publicApi = new TheatreSequence(this)
this._playbackControllerBox = new Box(
playbackController ?? new DefaultPlaybackController(coreTicker),
playbackController ?? new DefaultPlaybackController(getCoreTicker()),
)
this._statePointerDerivation = this._playbackControllerBox.derivation.map(
(playbackController) => playbackController.statePointer,
this._statePointerDerivation = prism(
() => this._playbackControllerBox.derivation.getValue().statePointer,
)
this._positionD = this._statePointerDerivation.flatMap((statePointer) =>
valueDerivation(statePointer.position),
)
this._positionD = prism(() => {
const statePointer = this._statePointerDerivation.getValue()
return val(statePointer.position)
})
this._positionFormatterD = this._subUnitsPerUnitD.map(
(subUnitsPerUnit) => new TimeBasedPositionFormatter(subUnitsPerUnit),
)
this._positionFormatterD = prism(() => {
const subUnitsPerUnit = val(this._subUnitsPerUnitD)
return new TimeBasedPositionFormatter(subUnitsPerUnit)
})
}
getIdentityDerivation(path: Array<string | number>): IDerivation<unknown> {

View file

@ -3,7 +3,7 @@ import {defer} from '@theatre/shared/utils/defer'
import type Sequence from './Sequence'
import type {IPlaybackDirection, IPlaybackRange} from './Sequence'
import AudioPlaybackController from './playbackControllers/AudioPlaybackController'
import coreTicker from '@theatre/core/coreTicker'
import {getCoreTicker} from '@theatre/core/coreTicker'
import type {Pointer} from '@theatre/dataverse'
import {notify} from '@theatre/shared/notify'
@ -289,7 +289,7 @@ export default class TheatreSequence implements ISequence {
await resolveAudioBuffer(args)
const playbackController = new AudioPlaybackController(
coreTicker,
getCoreTicker(),
decodedBuffer,
audioContext,
gainNode,

View file

@ -4,7 +4,7 @@ import type {
TrackData,
} from '@theatre/core/projects/store/types/SheetState_Historic'
import type {IDerivation, Pointer} from '@theatre/dataverse'
import {ConstantDerivation, prism, val} from '@theatre/dataverse'
import {prism, val} from '@theatre/dataverse'
import type {IUtilContext} from '@theatre/shared/logger'
import type {SerializableValue} from '@theatre/shared/utils/types'
import UnitBezier from 'timing-function/lib/UnitBezier'
@ -36,12 +36,12 @@ export default function interpolationTripleAtPosition(
'driver',
() => {
if (!track) {
return new ConstantDerivation(undefined)
return prism(() => undefined)
} else if (track.type === 'BasicKeyframedTrack') {
return _forKeyframedTrack(ctx, track, timeD)
} else {
ctx.logger.error(`Track type not yet supported.`)
return new ConstantDerivation(undefined)
return prism(() => undefined)
}
},
[track],
@ -79,7 +79,7 @@ function _forKeyframedTrack(
})
}
const undefinedConstD = new ConstantDerivation(undefined)
const undefinedConstD = prism(() => undefined)
function updateState(
ctx: IUtilContext,
@ -159,7 +159,7 @@ const states = {
started: true,
validFrom: -Infinity,
validTo: kf.position,
der: new ConstantDerivation({left: kf.value, progression: 0}),
der: prism(() => ({left: kf.value, progression: 0})),
}
},
lastKeyframe(kf: Keyframe): IStartedState {
@ -167,7 +167,7 @@ const states = {
started: true,
validFrom: kf.position,
validTo: Infinity,
der: new ConstantDerivation({left: kf.value, progression: 0}),
der: prism(() => ({left: kf.value, progression: 0})),
}
},
between(
@ -180,7 +180,7 @@ const states = {
started: true,
validFrom: left.position,
validTo: right.position,
der: new ConstantDerivation({left: left.value, progression: 0}),
der: prism(() => ({left: left.value, progression: 0})),
}
}

View file

@ -228,7 +228,8 @@ export default class SheetObjectTemplate {
*/
getMapOfValidSequenceTracks_forStudio(): IDerivation<IPropPathToTrackIdTree> {
return this._cache.get('getMapOfValidSequenceTracks_forStudio', () =>
this.getArrayOfValidSequenceTracks().map((arr) => {
prism(() => {
const arr = val(this.getArrayOfValidSequenceTracks())
let map = {}
for (const {pathToProp, trackId} of arr) {

View file

@ -1,6 +1,6 @@
import {privateAPI, setPrivateAPI} from '@theatre/core/privateAPIs'
import type {IProject} from '@theatre/core/projects/TheatreProject'
import coreTicker from '@theatre/core/coreTicker'
import {getCoreTicker} from '@theatre/core/coreTicker'
import type {ISheet} from '@theatre/core/sheets/TheatreSheet'
import type {SheetObjectAddress} from '@theatre/shared/utils/addresses'
import SimpleCache from '@theatre/shared/utils/SimpleCache'
@ -158,7 +158,7 @@ export default class TheatreSheetObject<
}
onValuesChange(fn: (values: this['value']) => void): VoidFn {
return this._valuesDerivation().tapImmediate(coreTicker, fn)
return this._valuesDerivation().tapImmediate(getCoreTicker(), fn)
}
// internal: Make the deviration keepHot if directly read

View file

@ -7,7 +7,7 @@ import type {
} from '@theatre/core/sheets/TheatreSheet'
import TheatreSheet from '@theatre/core/sheets/TheatreSheet'
import type {SheetAddress} from '@theatre/shared/utils/addresses'
import {Atom, valueDerivation} from '@theatre/dataverse'
import {Atom, prism, val} from '@theatre/dataverse'
import type SheetTemplate from './SheetTemplate'
import type {ObjectAddressKey, SheetInstanceId} from '@theatre/shared/utils/ids'
import type {StrictRecord} from '@theatre/shared/utils/types'
@ -88,15 +88,21 @@ export default class Sheet {
getSequence(): Sequence {
if (!this._sequence) {
const lengthD = valueDerivation(
this.project.pointers.historic.sheetsById[this.address.sheetId].sequence
.length,
).map(sanitizeSequenceLength)
const lengthD = prism(() => {
const unsanitized = val(
this.project.pointers.historic.sheetsById[this.address.sheetId]
.sequence.length,
)
return sanitizeSequenceLength(unsanitized)
})
const subUnitsPerUnitD = valueDerivation(
this.project.pointers.historic.sheetsById[this.address.sheetId].sequence
.subUnitsPerUnit,
).map(sanitizeSequenceSubUnitsPerUnit)
const subUnitsPerUnitD = prism(() => {
const unsanitized = val(
this.project.pointers.historic.sheetsById[this.address.sheetId]
.sequence.subUnitsPerUnit,
)
return sanitizeSequenceSubUnitsPerUnit(unsanitized)
})
this._sequence = new Sequence(
this.template.project,

View file

@ -6,7 +6,7 @@ import type {ProjectState_Historic} from '@theatre/core/projects/store/storeType
import type {SheetState_Historic} from '@theatre/core/projects/store/types/SheetState_Historic'
import * as t from '@theatre/core/propTypes'
import getStudio from '@theatre/studio/getStudio'
import coreTicker from '@theatre/core/coreTicker'
import {getCoreTicker} from '@theatre/core/coreTicker'
import globals from './globals'
import type {SheetId} from './utils/ids'
/* eslint-enable no-restricted-syntax */
@ -42,7 +42,7 @@ export async function setupTestSheet(sheetState: SheetState_Historic) {
state: projectState,
})
const ticker = coreTicker
const ticker = getCoreTicker()
ticker.tick()
await project.ready

View file

@ -109,7 +109,7 @@ export default function useKeyboardShortcuts() {
)
const playbackPromise = seq.playDynamicRange(
controlledPlaybackStateD.map(({range}) => range),
prism(() => val(controlledPlaybackStateD).range),
)
const playbackStateBox = getPlaybackStateBox(seq)