Skip to content

Commit

Permalink
chore(playground): add memory test comparing Tres and plain Vue/THREE…
Browse files Browse the repository at this point in the history
… canvas performance (#917)
  • Loading branch information
alvarosabu authored Feb 6, 2025
1 parent db93014 commit 45f215c
Showing 1 changed file with 133 additions and 41 deletions.
174 changes: 133 additions & 41 deletions playground/vue/src/pages/advanced/MemoryTresObjects.vue
Original file line number Diff line number Diff line change
@@ -1,72 +1,164 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import type { Group, Material } from 'three'
import { BoxGeometry, Color, Mesh, MeshBasicMaterial, PerspectiveCamera, Scene, Vector3, WebGLRenderer } from 'three'
import { onUnmounted, ref } from 'vue'
const toggleMax = 1000
const toggleMax = 400
const numObjectsMax = 2000
const startTimeMS = Date.now()
const startTimeMS = ref(0)
const width = 900
const height = 600
const toggleCount = ref(0)
const show = ref(false)
const msg = ref('Test is running.')
const showTres = ref(false)
const showVueThree = ref(false)
const msg = ref('Click Start Test to begin.')
const r = ref(null)
const isPaused = ref(true)
let intervalId: ReturnType<typeof setInterval>
const startInterval = () => {
intervalId = setInterval(() => {
const testVueThree = (() => {
let renderer: WebGLRenderer | null = null
let scene: Scene | null = null
let camera: PerspectiveCamera | null = null
let frameCount = 0
function testVueThree() {
if (toggleCount.value < toggleMax) {
// NOTE: Make sure that objects are mounted by
// checking `!!r.value`.
if (r.value) {
show.value = false
toggleCount.value++
if (renderer) {
if (frameCount < 2) {
frameCount++
renderer.render(scene!, camera!)
}
else {
camera?.removeFromParent()
scene!.children.forEach((m) => { ((m as Mesh).material as Material).dispose(); (m as Mesh).geometry.dispose() })
renderer.dispose()
frameCount = 0
camera = null
scene = null
renderer = null
showVueThree.value = false
toggleCount.value++
}
}
else {
renderer = new WebGLRenderer({ canvas: r.value })
renderer.setSize(width, height)
renderer.setClearColor(new Color('#EEE'))
scene = new Scene()
camera = new PerspectiveCamera()
camera.position.x = 10
camera.position.y = 10
camera.lookAt(new Vector3(0, 0, 0))
for (let i = 0; i < numObjectsMax; i++) {
scene.add(new Mesh(new BoxGeometry(), new MeshBasicMaterial()))
}
scene.add(camera)
renderer.render(scene, camera)
}
}
else {
show.value = true
else if (!showVueThree.value) {
showVueThree.value = true
}
}
else {
const elapsedSec = (Date.now() - startTimeMS.value) / 1000
msg.value = `Plain Vue/THREE test completed in ${elapsedSec} seconds.`
clearInterval(intervalId)
const elapsedSec = (Date.now() - startTimeMS) / 1000
msg.value = `Test completed in ${elapsedSec} seconds.`
}
}, 1000 / 120)
}
const togglePause = () => {
isPaused.value = !isPaused.value
if (!isPaused.value) {
startInterval()
}
else {
clearInterval(intervalId)
return testVueThree
})()
const testTres = (() => {
let frameCount = 0
return () => {
if (toggleCount.value < toggleMax) {
if (r.value && frameCount < 2) {
// NOTE: Wait until Tres has actually rendered before
// removing the canvas.
((r.value as Group).children[0] as Mesh).onAfterRender = () => { frameCount++ }
}
else {
if (frameCount < 1) {
showTres.value = true
}
else {
toggleCount.value++
showTres.value = false
frameCount = 0
}
}
}
else {
const elapsedSec = (Date.now() - startTimeMS.value) / 1000
msg.value = `Tres test completed in ${elapsedSec} seconds.`
clearInterval(intervalId)
}
}
})()
const isStarted = ref(false)
const startTestTres = () => {
isStarted.value = true
startTimeMS.value = Date.now()
// NOTE: Using `setInterval`; it typically will keep
// running in situations were `requestAnimationFrame` will pause.
intervalId = setInterval(testTres, 1000 / 60)
msg.value = 'Test is running...'
}
onUnmounted(() => clearInterval(intervalId))
const startTestVueThree = () => {
isStarted.value = true
startTimeMS.value = Date.now()
// NOTE: Using `setInterval`; it typically will keep
// running in situations were `requestAnimationFrame` will pause.
intervalId = setInterval(testVueThree, 1000 / 60)
msg.value = 'Test is running...'
}
onUnmounted(() => {
clearInterval(intervalId)
})
</script>

<template>
<OverlayInfo>
<h1>Memory test: Tres Objects</h1>
<h1>Memory test: Canvases with objects – Tres vs Plain Vue/THREE</h1>
<p><span style="color: red">IMPORTANT</span> Epileptic warning: the tests run on this page cause the screen to flash rapidly.</p>
<h2>Setup</h2>
<p>This page will successively create and remove a TresCanvas containing a number of objects.</p>
<p>This test will create and remove {{ toggleMax }} canvas instances with {{ numObjectsMax }} objects/materials/geometries each.</p>
<h2>Note</h2>
<ul>
<li>These tests are intended to help spot memory leaks.</li>
<li>Faster/slower test duration does not indicate a problem.</li>
</ul>
<h2>Status</h2>
<p>{{ msg }}</p>
<p>Number of TresCanvases created: {{ toggleCount }} / {{ toggleMax }}</p>
<p>Number of Objects per TresCanvas: {{ numObjectsMax }}</p>
<button style="padding: 8px 16px; margin-top: 10px;" @click="togglePause">
{{ isPaused ? 'Start Test' : 'Pause Test' }}
<p>Number of canvases created: {{ toggleCount }} / {{ toggleMax }}</p>
<button
v-if="!isStarted"
style="padding: 8px 16px; margin-top: 10px;"
@click="startTestTres"
>
Start Tres test
</button>

<button
v-if="!isStarted"
style="padding: 8px 16px; margin-top: 10px;"
@click="startTestVueThree"
>
Start plain Vue/THREE test
</button>
</OverlayInfo>
<div v-if="show" style="width: 90%; height: 90%; border: 1px solid #F00">
<TresCanvas clear-color="black">
<TresGroup ref="r" />
<TresMesh v-for="_, i of Array.from({ length: numObjectsMax })" :key="i">
<TresMeshBasicMaterial />
<TresBoxGeometry />
</TresMesh>
<div v-if="showTres" :style="{ width: `${width}px`, height: `${height}px` }">
<TresCanvas clear-color="#EEE">
<TresGroup ref="r">
<TresMesh v-for="_, i of Array.from({ length: numObjectsMax })" :key="i">
<TresMeshBasicMaterial />
<TresBoxGeometry />
</TresMesh>
</TresGroup>
</TresCanvas>
</div>
<div v-if="showVueThree">
<canvas ref="r" clear-color="black"></canvas>
</div>
</template>

0 comments on commit 45f215c

Please sign in to comment.