Giter Site home page Giter Site logo

utsuboco / r3f-perf Goto Github PK

View Code? Open in Web Editor NEW
560.0 5.0 20.0 4.04 MB

Easily monitor your ThreeJS performances.

Home Page: https://codesandbox.io/s/perlin-cubes-r3f-perf-wtp9t?file=/src/App.js

License: MIT License

JavaScript 1.49% TypeScript 98.51%
threejs r3f performance-analysis performance-monitoring performance benchmark profiling monitor react

r3f-perf's Introduction

npm npm

R3F-Perf

Changelog

Easily monitor the performances of your @react-three/fiber application.

Add the Perf component anywhere in your Canvas.

Installation

yarn add --dev r3f-perf

Options

logsPerSecond?: 10, // Refresh rate of the logs
antialias?: true, // Take a bit more performances but render the text with antialiasing
overClock?: false, // Disable the limitation of the monitor refresh rate for the fps
deepAnalyze?: false, // More detailed informations about gl programs
showGraph?: true // show the graphs
minimal?: false // condensed version with the most important informations (gpu/memory/fps/custom data)
customData?: {
  value: 0, // initial value,
  name: '', // name to show
  round: 2, // precision of the float
  info: '', // additional information about the data (fps/ms for instance)
}
matrixUpdate?: false // count the number of time matrixWorldUpdate is called per frame
chart?: {
  hz: 60, // graphs refresh frequency parameter
  length: 120, // number of values shown on the monitor
}
colorBlind?: false // Color blind colors for accessibility
className?: '' // override CSS class
style?: {} // override style
position?: 'top-right'|'top-left'|'bottom-right'|'bottom-left' // quickly set the position, default is top-right

Usage

import { Canvas } from '@react-three/fiber'
import { Perf } from 'r3f-perf'

function App() {
  return (
    <Canvas>
      <Perf />
    </Canvas>
  )
}

Usage without interface : PerfHeadless

Codesandbox Example

import { Canvas } from '@react-three/fiber'
import { PerfHeadless, usePerf } from 'r3f-perf'

const PerfHook = () => {
  // getPerf() is also available for non-reactive way
  const [gl, log, getReport] = usePerf((s) => s[(s.gl, s.log, s.getReport)])
  console.log(gl, log, getReport())
  return <PerfHeadless />
}

function App() {
  return (
    <Canvas>
      <PerfHook />
    </Canvas>
  )
}

Custom Data

import { setCustomData, getCustomData } from 'r3f-perf'

const UpdateCustomData = () => {
  // recommended to throttle to 1sec for readability
  useFrame(() => {
    setCustomData(55 + Math.random() * 5) // will update the panel with the current information
  })
  return null
}

SSR

The tool work with any server side rendering framework. You can try with Next and @react-three/fiber using this starter : https://github.com/pmndrs/react-three-next

Maintainers :

r3f-perf's People

Contributors

alaricbaraou avatar alexandernanberg avatar codyjasonbennett avatar dependabot-preview[bot] avatar neciszhang avatar quirm avatar renaudrohlinger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

r3f-perf's Issues

Using with a drei fork

Hey utsuboco peeps! ๐Ÿ‘‹

I had to fork drei for some very specific issues in my project and force module resolution to use my version. That's fine and dandy but then I get this error:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@react-three/drei' imported from /.../node_modules/.pnpm/r3f-perf

Would setting drei as a peer dependency for r3f-perf help with this?

Difficult to import production version of component into Typescript project

Importing the component to show in production as shown in the readme poses a lot of difficulties in Typescript, would it be better perhaps to maybe be able to flag an .env variable instead? The use case being, we're doing a lot of exploration into models, complex scenes etc. and seeing how it performs in production is really valuable.

Improve GPU ratio

Add the Drei helper useDetectGPU to detect the quality of the GPU and then make a ratio between the GPU rank, the number of triangles, lines, and points of the scene + the number of render calls.

render resolution or pixel ratio

It would be super helpful to show the render resolution or pixel ratio alongside all of the other stats, please consider it a feature request!

In particular, this would be a superpower as a debug or performance tool along side drei's PerformanceMonitor

DependencyNotFoundError

The issue:

When installing r3f-perf and importing the component, the following error occurs:

DependencyNotFoundError

Could not find dependency: '@react-icons/all-files' relative to '/node_modules/r3f-perf/dist/r3f-perf.cjs.development.js'

Example Codesandbox: https://codesandbox.io/s/upbeat-pasteur-mvx5d?file=/src/App.js

I suspect that the dev dependencies aren't being installed by default when the package is downloaded, but I could be wrong. Happy to have a closer look tomorrow (it's 2am so I need to get some sleep.)

Cheers

Position and/or className support

Fantastic lib, thanks for formalizing this into a new standard package for r3f.

Using this with other dev tool libraries such as https://github.com/pmndrs/use-tweaks causes UI collisions as they are both positioned in the top right. Thoughts on adding support for position (top, right, bottom, left) and/or className support on <Perf /> so manual CSS overrides are possible?

Wrong count of geometry

While following the awesome three-js journey lessons from Bruno Simon, I came to realize there is an issue with r3f-perf on counting geometries.
Although we should have just one geometry in the below example;
r3f-perf shows 100 (those in the loop are counted separately when in reality they are just one geometry)

import { OrbitControls } from '@react-three/drei'
import { Perf } from 'r3f-perf'
import { useRef } from 'react'
import * as THREE from 'three'

const torusGeometry = new THREE.TorusGeometry(1, 0.6, 16, 32)

export default function Experience()
{
    const donuts = useRef([])

    return <>

        <Perf position="top-left" />

        <OrbitControls makeDefault />

        { [...Array(100)].map((value, index) =>
            <mesh
                ref={ (element) => donuts.current[index] = element }
                key={ index }
                geometry={ torusGeometry }
                position={ [
                    (Math.random() - 0.5) * 10,
                    (Math.random() - 0.5) * 10,
                    (Math.random() - 0.5) * 10
                ] }
                scale={ 0.2 + Math.random() * 0.2 }
                rotation={ [
                    Math.random() * Math.PI,
                    Math.random() * Math.PI,
                    0
                ] }
            >
                <torusGeometry args={ [ 1, 0.6, 16, 32 ] } />
            </mesh>
        ) }

    </>
}

Am I missing something?
Using latest v6 r3f-perf version (6.6.3; but the most recent v7 doesn't seem to mention this issue)

Toggle Button covers panel

Just a small issue and probably an easy fix: The toggle button covers the panel and in the "bottom-right" position it makes it difficult to read the value for the triangles.
Screen Shot 2021-06-03 at 2 22 16 PM
Screen Shot 2021-06-03 at 2 22 39 PM

Edit: I just noticed this might be a Problem with Chakra UI since this issue only appears when using Chakra UI. I believe Chakra UI uses some global CSS resets. Maybe that's what's causing it.

Excessive bundle size

Hi, we love your tool. However, it depends on react-icons which adds >6mb to our bundle size. We had to lazy load <Perf> as a result. Maybe that's something you should write about in the docs?

Consider allowing r3f-perf to be used for production environments.

Hey there, love the package, thanks for making it!

I was wondering if you'd consider removing the code that ensures that r3f-perf can only be used for the development environment.

I think it'd make more sense to allow the user to determine within their own app under what conditions they want to include the component.

Right now I wanted to check the frame rate for a build / production version of my game, but I've had to fork the repo in order to do so.

Cheers!

various "unsupported GPOS table" log in console

Hi,

I'm seeing the following errors when the r3f-perf -> component is rendered.

unsupported GPOS table LookupType 8 format 2
unsupported GPOS table LookupType 5 format 1
unsupported GSUB table LookupType 6 format 2
unsupported GSUB table LookupType 6 format 1
unsupported GPOS table LookupType 8 format 2
unsupported GPOS table LookupType 5 format 1
unsupported GSUB table LookupType 6 format 2
unsupported GSUB table LookupType 6 format 1

I've created a small sandbox https://codesandbox.io/p/sandbox/r3f-perf-gpos-repro-tqz5kw.

Repro steps:

  1. Open the sandbox
  2. Open the browser console
  3. See the console logs.
  4. Remove the component,
  5. See unsupported GPOS table logs no longer appear

This doesn't seem to be breaking anything but is annoying to see issues as I wasn't sure if it was my application causing the issues before I narrowed it down to this lib.

`render.calls` is always 0

Issue

https://codesandbox.io/s/r3f-perf-issue-with-gl-0do0bm

const perf = getPerf()
console.log(perf.gl?.info.render.calls) // 0
console.log(perf.gl?.info.render.triangles) // 0

I think this is because of the gl.info.reset() in https://github.com/utsuboco/r3f-perf/blob/main/src/components/PerfHeadless.tsx#L262

Possible fix

Could we save render.calls and render.triangles in the store? In this way we don't break code which relies on that number.

Possible workaround

const info = usePerf((state) => state.gl?.info)
    
useFrame((state) => {
    const { camera, gl, scene } = state
    gl.render(scene, camera)
    console.log(info.render.frames) 
}, 1)

I'm not sure though if this can cause some issue. Do gl.render() gets called twice in this way? Once for useFrame(...,1) and then for useFrame(..., Infinity)?

const Renderer = () =>{
useFrame(function updateR3FPerf({ gl, scene, camera }) {
camera.updateMatrix()
matriceCount.value -= 1
camera.matrixWorld.copy(camera.matrix)
camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
gl.render(scene,camera)
matriceWorldCount.value = 0
matriceCount.value = 0
}, Infinity)
return null
}

'FramebufferTexture' is not exported from 'three'

Awesome package! Just a heads up, when trying to use the component, I get the error:

./node_modules/three-stdlib/objects/Lensflare.js
Attempted import error: 'FramebufferTexture' is not exported from 'three'.

Error on Next.js 14.1.0 - Window is not defined

I just updated to Next.js v14.1.0 and it is breaking r3-perf.
I am getting the error ReferenceError: window is not defined

Before, I've been using Next.js v14.0.4 without any issue with r3-perf.

Is this a known issue and any suggestion for fixing it?

TypeError: create is not a function

I'm running into this error only by adding the <Perf /> component.

My project is also using zustand, could there be some conflict or something...?

store.js:11 Uncaught TypeError: create is not a function
    at ./node_modules/r3f-perf/dist/store.js (store.js:11:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at ./node_modules/r3f-perf/dist/index.js (index.js:3:15)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
...

How to use r3f-perf (react-three-next)?

Adding r3f-perf to react-three-next and using the component inside layout/canvas gives me following error:
Uncaught R3F hooks can only be used within the Canvas component!
I use the component inside Canvas. In any other app it works.
Here is my package.json:

  "dependencies": {
    "@babel/plugin-transform-runtime": "^7.17.0",
    "@react-three/drei": "^9.2.0",
    "@react-three/fiber": "^8.0.10",
    "babel-plugin-glsl": "^1.0.0",
    "glsl-random": "^0.0.5",
    "next": "^12.1.4",
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "three": "^0.139.2",
    "three-stdlib": "^2.9.1",
    "zustand": "^3.7.2"
  },
  "devDependencies": {
    "@next/bundle-analyzer": "^12.0.10",
    "autoprefixer": "^10.4.2",
    "eslint": "^8.8.0",
    "eslint-config-next": "^12.0.10",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-tailwind": "^0.2.1",
    "file-loader": "^6.2.0",
    "glslify": "^7.1.1",
    "glslify-loader": "^2.0.0",
    "next-compose-plugins": "^2.2.1",
    "next-offline": "^5.0.5",
    "postcss": "^8.4.12",
    "prettier": "^2.6.2",
    "r3f-perf": "^6.0.1",
    "raw-loader": "^4.0.2",
    "tailwindcss": "^3.0.23",
    "url-loader": "^4.1.1"
  }

And here is where I use the component:

    <Canvas
      mode='concurrent'
      style={{
        position: 'absolute',
        top: 0,
      }}
      onCreated={(state) => state.events.connect(dom.current)}
    >
      <Perf />
      <LControl />
      <Preload all />
      {children}
    </Canvas>

Usage with demand frameloop

Hey mate! Love the tool. Is there any advice in how to use it when frameloop is set to "demand"? When it is you don't get FPS data, and calls, triangles, and lines display only for the render frame and then drop off immediately.

It would be great if the data would persist between frames (when there is no rendering happening). Is FPS calculated with useFrame? Could it be calcuated with rAF instead so it works when frameloop is demand?

GPU/Memory/FPS aren't calculated at all.

Keen to discuss.

Cannot read property 'render' of undefined

Happens when you toggle canvas off/on.

See https://codesandbox.io/s/amazing-benz-f97gj?file=/src/App.tsx

Cannot read property 'render' of undefined
GLPerf.paramLogger
https://f97gj.csb.app/node_modules/r3f-perf/dist/r3f-perf.cjs.development.js:1260:45
_loop
https://f97gj.csb.app/node_modules/r3f-perf/dist/r3f-perf.cjs.development.js:1091:18
GLPerf.nextFrame
https://f97gj.csb.app/node_modules/r3f-perf/dist/r3f-perf.cjs.development.js:1109:11
Array.eval
https://f97gj.csb.app/node_modules/r3f-perf/dist/r3f-perf.cjs.development.js:1295:19
renderLoop
https://f97gj.csb.app/node_modules/react-three-fiber/web.js:262:26

React 18 support

I'd like to use r3f-perf with the nearly released React 18. When I do, I get the warning

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

Inaccurate results in Firefox

It seems like the GPU timing and memory is not accurate in Firefox:

ff

There's no way to have each frame take 40ms and still get 60fps so this is clearly inaccurate.

Compare this to the same app running in Chrome:
cr

In Firefox I get this console message:

Disjoint_time_query extension not available.

Sure enough, the extension is Chrome only.

Given this, would it be possible to note in the readme that the GPU measurements only work in Chrome? Or even better, hide the inaccurate results completely when the extension is not available.

No Graph/Chart when disabling/re-enabling component

When disabling (not rendering) component and re-enabling it, the graphs/charts are not shown anymore.
Two different methods tried:

{perf_toggle ? <Perf position={perf_pos} /> : null}
or
<Perf headless={perf_toggle} position={perf_pos} />

both with same result: Graph/Chart not show the component activated second time:
e.g. using here 2nd example

  1. perf_toggle = true => perf GUI not shown (as expected)

  2. perf_toggle = false => perf GUI shown with Graph (as expected)
    Screenshot 2021-10-29 at 06 06 51

  3. perf_toggle = true => perf GUI not shown (as expected)

  4. perf_toggle = false => perf GUI shown WITHOUT Graph
    Screenshot 2021-10-29 at 06 08 53

Error when adding a Drei <Text> component - Cannot read property 'muiPerf' of undefined

If you add a Text component from Drei to the scene r3f-perf fails with the error "Cannot read property 'muiPerf' of undefined"

r3f-perf.esm.js?1e43:524 Uncaught TypeError: Cannot read property 'muiPerf' of undefined
    at eval (r3f-perf.esm.js?1e43:524)
    at Text.traverse (three.module.js?5a89:7077)
    at Group.traverse (three.module.js?5a89:7083)
    at Scene.traverse (three.module.js?5a89:7083)
    at Array.eval (r3f-perf.esm.js?1e43:517)
    at run (react-three-fiber.esm.js?ef10:1287)
    at loop (react-three-fiber.esm.js?ef10:1326)

i have edited the basic codesandbox adding a test Text at https://codesandbox.io/s/perlin-cubes-forked-thrux so you can replicate the error easily.

am i doing something wrong like not having a material on the Text component or is this a edge case of the library?

Thanks for this amazing component!

Potential performance issues (with web workers)?

Feel free to close / ignore this issue, as it's a bit niche I believe. But I think r3f-perf is having performance issues with web workers, (though it might not even be specific to that.)

I noticed that messages from my physics web worker occasionally would take awhile to be received. Mesages could be delayed by well over 30+ms vs the typical < 1ms

After spending awhile debugging, it seems that removing <Perf/> from my app immediately resolved the issue.

I've uploaded a recording here:

https://gfycat.com/snivelingpersonalanglerfish

In the beginning I'm demonstrating without <Perf/> included, the object moves fine. Then upon reload I demonstrate with <Perf headless /> included, which becomes choppy and in the console messages are printed when the physics is falling out of sync with the main thread (due to message delay).

Then what's probably most useful is from the 43 second mark with <Perf/> added, you can see the GPU graph has spiked and the time displayed is well beyond what one would expect.

Note, this is all from a desktop pc, so it has a decent gpu.

The interesting thing is, the joystick that runs on the main thread never seems to lag, so it's not as if the performance of the website overall is dropping, it's just that the web worker messages are being delayed.

Anyway, this isn't urgent or anything, I just wanted to flag it in case you wanted to know, but it's not a big issue. So feel free to close!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.