Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions packages/motion-dom/src/animation/JSAnimation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
secondsToMilliseconds,
} from "motion-utils"
import { time } from "../frameloop/sync-time"
import { activeAnimations } from "../stats/animation-count"
import { mix } from "../utils/mix"
import { Mixer } from "../utils/mix/types"
import { frameloopDriver } from "./drivers/frame"
Expand Down Expand Up @@ -91,7 +90,6 @@ export class JSAnimation<T extends number | string>

constructor(options: ValueAnimationOptions<T>) {
super()
activeAnimations.mainThread++

this.options = options
this.initAnimation()
Expand Down Expand Up @@ -526,7 +524,6 @@ export class JSAnimation<T extends number | string>
this.state = "idle"
this.stopDriver()
this.startTime = this.holdTime = null
activeAnimations.mainThread--
}

private stopDriver() {
Expand Down
16 changes: 1 addition & 15 deletions packages/motion-dom/src/animation/waapi/start-waapi-animation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { activeAnimations } from "../../stats/animation-count"
import { statsBuffer } from "../../stats/buffer"
import { ValueKeyframesDefinition, ValueTransition } from "../types"
import { mapEasingToNativeEasing } from "./easing/map-easing"

Expand Down Expand Up @@ -29,10 +27,6 @@ export function startWaapiAnimation(
*/
if (Array.isArray(easing)) keyframeOptions.easing = easing

if (statsBuffer.value) {
activeAnimations.waapi++
}

const options: KeyframeAnimationOptions = {
delay,
duration,
Expand All @@ -44,13 +38,5 @@ export function startWaapiAnimation(

if (pseudoElement) options.pseudoElement = pseudoElement

const animation = element.animate(keyframeOptions, options)

if (statsBuffer.value) {
animation.finished.finally(() => {
activeAnimations.waapi--
})
}

return animation
return element.animate(keyframeOptions, options)
}
5 changes: 1 addition & 4 deletions packages/motion-dom/src/frameloop/batcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ export function createRenderBatcher(
const flagRunNextFrame = () => (runNextFrame = true)

const steps = stepsOrder.reduce((acc, key) => {
acc[key] = createRenderStep(
flagRunNextFrame,
allowKeepAlive ? key : undefined
)
acc[key] = createRenderStep(flagRunNextFrame)
return acc
}, {} as Steps)

Expand Down
18 changes: 1 addition & 17 deletions packages/motion-dom/src/frameloop/render-step.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { statsBuffer } from "../stats/buffer"
import { StepNames } from "./order"
import { FrameData, Process, Step } from "./types"

export function createRenderStep(
runNextFrame: () => void,
stepName?: StepNames
): Step {
export function createRenderStep(runNextFrame: () => void): Step {
/**
* We create and reuse two queues, one to queue jobs for the current frame
* and one for the next. We reuse to avoid triggering GC after x frames.
Expand All @@ -32,15 +27,12 @@ export function createRenderStep(
isProcessing: false,
}

let numCalls = 0

function triggerCallback(callback: Process) {
if (toKeepAlive.has(callback)) {
step.schedule(callback)
runNextFrame()
}

numCalls++
callback(latestFrameData)
}

Expand Down Expand Up @@ -93,14 +85,6 @@ export function createRenderStep(
// Execute this frame
thisFrame.forEach(triggerCallback)

/**
* If we're recording stats then
*/
if (stepName && statsBuffer.value) {
statsBuffer.value.frameloop[stepName].push(numCalls)
}
numCalls = 0

// Clear the frame so no callbacks remain. This is to avoid
// memory leaks should this render step not run for a while.
thisFrame.clear()
Expand Down
1 change: 0 additions & 1 deletion packages/motion-dom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ export * from "./resize"
export * from "./scroll/observe"

export * from "./stats"
export * from "./stats/animation-count"
export * from "./stats/buffer"
export * from "./stats/types"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { HTMLVisualElement } from "../../render/html/HTMLVisualElement"
import type { ResolvedValues } from "../../render/types"
import { scaleCorrectors } from "../../render/utils/is-forced-motion-value"
import type { MotionStyle, VisualElement } from "../../render/VisualElement"
import { activeAnimations } from "../../stats/animation-count"
import { statsBuffer } from "../../stats/buffer"
import { delay } from "../../utils/delay"
import { isSVGElement } from "../../utils/is-svg-element"
Expand Down Expand Up @@ -1733,7 +1732,6 @@ export function createProjectionNode<I>({
this.pendingAnimation = frame.update(() => {
globalProjectionState.hasAnimatedSinceResize = true

activeAnimations.layout++
this.motionValue ||= motionValue(0)
this.motionValue.jump(0, false)

Expand All @@ -1748,11 +1746,7 @@ export function createProjectionNode<I>({
this.mixTargetDelta(latest)
options.onUpdate && options.onUpdate(latest)
},
onStop: () => {
activeAnimations.layout--
},
onComplete: () => {
activeAnimations.layout--
options.onComplete && options.onComplete()
this.completeAnimation()
},
Expand Down
146 changes: 31 additions & 115 deletions packages/motion-dom/src/stats/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,130 +1,46 @@
import { MotionGlobalConfig } from "motion-utils"
import { recordStats } from ".."
import { frame, frameData } from "../../frameloop"

MotionGlobalConfig.useManualTiming = true
import { statsBuffer } from "../buffer"

describe("recordStats", () => {
it("should throw an error if stats are already being measured", () => {
expect(() => {
recordStats()
recordStats()
}).toThrow()
beforeEach(() => {
statsBuffer.value = null
statsBuffer.addProjectionMetrics = null
})

it("should return the correct stats", async () => {
return new Promise<void>((resolve) => {
const record = recordStats()

frameData.timestamp = 15
frameData.delta = 1000 / 60

frame.update(() => {})

frame.render(() => {
queueMicrotask(() => {
const stats = record()

const {
rate,
read,
resolveKeyframes,
update,
preRender,
render,
postRender,
} = stats.frameloop

expect(rate.min).toEqual(60)
expect(rate.max).toEqual(60)
expect(rate.avg).toEqual(60)
expect(read.min).toEqual(0)
expect(read.max).toEqual(0)
expect(read.avg).toEqual(0)
expect(resolveKeyframes.min).toEqual(0)
expect(resolveKeyframes.max).toEqual(0)
expect(resolveKeyframes.avg).toEqual(0)
expect(update.min).toEqual(1)
expect(update.max).toEqual(1)
expect(update.avg).toEqual(1)
expect(preRender.min).toEqual(0)
expect(preRender.max).toEqual(0)
expect(preRender.avg).toEqual(0)
expect(render.min).toEqual(1)
expect(render.max).toEqual(1)
expect(render.avg).toEqual(1)
it("throws if stats are already being measured", () => {
recordStats()
expect(() => recordStats()).toThrow()
})

// postRender always at least 1 as stats itself uses a postRender step
expect(postRender.min).toEqual(1)
expect(postRender.max).toEqual(1)
expect(postRender.avg).toEqual(1)
it("initializes the layout projection buffer", () => {
recordStats()

resolve()
})
})
expect(statsBuffer.value).not.toBeNull()
expect(statsBuffer.value!.layoutProjection).toEqual({
nodes: [],
calculatedTargetDeltas: [],
calculatedProjections: [],
})
})

it("should return the correct stats across multiple frames", async () => {
return new Promise<void>((resolve) => {
const record = recordStats()

frameData.timestamp = 15
frameData.delta = 1000 / 60
it("addProjectionMetrics appends per-frame metrics", () => {
recordStats()

frame.update(() => {})

frame.render(() => {})

frame.postRender(() => {
frameData.timestamp = 30
frameData.delta = 1000 / 30

frame.update(() => {})
frame.update(() => {})
frame.update(() => {})
frame.render(() => {
queueMicrotask(() => {
const stats = record()

const {
rate,
read,
resolveKeyframes,
update,
preRender,
render,
postRender,
} = stats.frameloop

expect(rate.min).toEqual(30)
expect(rate.max).toEqual(60)
expect(rate.avg).toEqual(40)
expect(read.min).toEqual(0)
expect(read.max).toEqual(0)
expect(read.avg).toEqual(0)
expect(resolveKeyframes.min).toEqual(0)
expect(resolveKeyframes.max).toEqual(0)
expect(resolveKeyframes.avg).toEqual(0)
expect(update.min).toEqual(1)
expect(update.max).toEqual(3)
expect(update.avg).toEqual(2)
expect(preRender.min).toEqual(0)
expect(preRender.max).toEqual(0)
expect(preRender.avg).toEqual(0)
expect(render.min).toEqual(1)
expect(render.max).toEqual(1)
expect(render.avg).toEqual(1)

// postRender always at least 1 as stats itself uses a postRender step
expect(postRender.min).toEqual(1)
expect(postRender.max).toEqual(2)
expect(postRender.avg).toEqual(1.5)
statsBuffer.addProjectionMetrics!({
nodes: 3,
calculatedTargetDeltas: 2,
calculatedProjections: 1,
})
statsBuffer.addProjectionMetrics!({
nodes: 4,
calculatedTargetDeltas: 0,
calculatedProjections: 2,
})

resolve()
})
})
})
expect(statsBuffer.value!.layoutProjection).toEqual({
nodes: [3, 4],
calculatedTargetDeltas: [2, 0],
calculatedProjections: [1, 2],
})
})
})
5 changes: 0 additions & 5 deletions packages/motion-dom/src/stats/animation-count.ts

This file was deleted.

8 changes: 2 additions & 6 deletions packages/motion-dom/src/stats/buffer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { StatsRecording } from "./types"
import type { LayoutProjectionMetrics, StatsRecording } from "./types"

export type InactiveStatsBuffer = {
value: null
Expand All @@ -7,11 +7,7 @@ export type InactiveStatsBuffer = {

export type ActiveStatsBuffer = {
value: StatsRecording
addProjectionMetrics: (metrics: {
nodes: number
calculatedTargetDeltas: number
calculatedProjections: number
}) => void
addProjectionMetrics: (metrics: LayoutProjectionMetrics) => void
}

export const statsBuffer: InactiveStatsBuffer | ActiveStatsBuffer = {
Expand Down
Loading