-
Notifications
You must be signed in to change notification settings - Fork 30
Context Spy #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Context Spy #110
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When enabled by the `enableContextSpy` renderer option, the canvas context object (WebGL in the current case) will be instrumented with a spy mechanism that counts the number of calls to each context function. The number of calls to each function during the previous FPS interval will be included in the new `contextSpyData` key of the 'fpsUpdate' event. The Context Spy can be enabled in Example Tests by the `contextSpy` boolean URL param. When enabled, a statistical calculation of each context function call will be reported after every FPS statistics summary. Because of this, the option requires that the `fps` URL param is also set to true, otherwise only a degradation of performance will occur without any output of the Context Spy data. Example output: ``` --------------------------------- Average FPS: 4.4 Median FPS: 4 P01 FPS: 4 P05 FPS: 4 P25 FPS: 4 Std Dev FPS: 0.48989794855663565 Num samples: 5 --------------------------------- median(disable) / median(fps): 4 median(clear) / median(fps): 1 median(bindBuffer) / median(fps): 1 median(bufferData) / median(fps): 1 median(getParameter) / median(fps): 3 median(activeTexture) / median(fps): 3 median(bindTexture) / median(fps): 3 median(uniform2fv) / median(fps): 3 median(uniform1f) / median(fps): 3 median(enable) / median(fps): 3 median(blendFunc) / median(fps): 3 median(drawElements) / median(fps): 3 median(totalCalls) / median(fps): 28 --------------------------------- ```` BREAKING CHANGE This is a breaking change because the 'fpsUpdate' event previously only used a `number` as its payload type, whereas now it is an object with the keys `fps` and `contextSpyData`. Apps/frameworks that listen for the 'fpsUpdate' event will need to update their handlers.
wouterlucas
approved these changes
Dec 20, 2023
Contributor
wouterlucas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat! This would be great base for a more advanced debugger of some kind, getting these calls/statistics is very useful.
github-merge-queue bot
pushed a commit
that referenced
this pull request
Jan 16, 2024
**Depends on #110** - **DO NOT MERGE** until that PR is merged to main, and be sure to set the base to `main` after that happens. This performance enhancement encapsulates the native WebGL context into a wrapper which keeps track of the state of some some heavy/frequent WebGL operations and filters out unnecessary calls to the native context. See description above the WebGlContextWrapper class for more information on it. # Performance Tests ## Chrome Desktop The test on Chrome Desktop on my 2019 MacBook Pro showed a significant improvement in FPS for 6000 nodes when running the `stress-multi-texture` test. Total WebGL calls per frame were reduced by 78% and the median FPS was improved by 98%. ``` stress-multi-texture (chrome) http://localhost:5173/?test=stress-multi-texture&overlay=false&fps=true&multiplier=60&contextSpy=true Created 6000 nodes with alternating textures Before: --------------------------------- Average FPS: 30 Median FPS: 30 P01 FPS: 30 P05 FPS: 30 P25 FPS: 30 Std Dev FPS: 0 Num samples: 100 --------------------------------- median(disable) / median(fps): 6202 median(clear) / median(fps): 1 median(bindBuffer) / median(fps): 1 median(bufferData) / median(fps): 1 median(getParameter) / median(fps): 6201 median(activeTexture) / median(fps): 6201 median(bindTexture) / median(fps): 6201 median(uniform2fv) / median(fps): 6201 median(uniform1f) / median(fps): 6201 median(enable) / median(fps): 6201 median(blendFunc) / median(fps): 6201 median(drawElements) / median(fps): 6201 median(totalCalls) / median(fps): 55813 --------------------------------- After: --------------------------------- Average FPS: 59.2 Median FPS: 59 (+96%) P01 FPS: 58 P05 FPS: 58 P25 FPS: 58 Std Dev FPS: 0.8602325267042625 Num samples: 100 --------------------------------- median(clear) / median(fps): 1 median(bufferData) / median(fps): 1 median(bindTexture) / median(fps): 6103 median(drawElements) / median(fps): 6103 median(totalCalls) / median(fps): 12207 (-78%) --------------------------------- ``` ## Raspberry Pi (RPI) For the same `stress-multi-texture` test at 100 nodes, the Raspberry PI B+ running WPE 2.42 showed no change in median FPS despite the total WebGL calls per frame being reduced the same amount. This seems to stem from the fact that the biggest bottle neck with running Lightning 3 on the RPI is the WebGL `bufferData()` operation which is a single operation that uploads the CPU bound Vertex Buffer to the GPU before drawing each frame. In a performance profile from the RPI, this operation accounts for 75% of the CPU time within 1 second of rendering, while on Chrome Desktop the time spent is very minimal. ``` stress-multi-texture (RPI) http://10.0.0.144:5173/?test=stress-multi-texture&overlay=false&resolution=1080&fps=true&multiplier=1 Created 100 nodes with alternating textures Before --------------------------------- Average FPS: 39.18 Median FPS: 45 P01 FPS: 23 P05 FPS: 24 P25 FPS: 27 Std Dev FPS: 9.643007829510463 Num samples: 100 --------------------------------- median(disable) / median(fps): 102 median(clear) / median(fps): 1 median(bindBuffer) / median(fps): 1 median(bufferData) / median(fps): 1 median(getParameter) / median(fps): 101 median(activeTexture) / median(fps): 101 median(bindTexture) / median(fps): 101 median(uniform2fv) / median(fps): 101 median(uniform1f) / median(fps): 101 median(enable) / median(fps): 101 median(blendFunc) / median(fps): 101 median(drawElements) / median(fps): 101 median(totalCalls) / median(fps): 913 --------------------------------- After --------------------------------- Average FPS: 38.57 Median FPS: 45 (+0%) P01 FPS: 24 P05 FPS: 24 P25 FPS: 28 Std Dev FPS: 8.771835611774769 Num samples: 100 --------------------------------- median(clear) / median(fps): 1 median(bufferData) / median(fps): 1 median(bindTexture) / median(fps): 101 median(drawElements) / median(fps): 101 median(totalCalls) / median(fps): 204 (-78%) --------------------------------- ```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
breaking change!
This issue / PR may require downstream dependencies to make changes to retain existing functionality
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When enabled by the
enableContextSpyrenderer option, the canvas context object (WebGL in the current case) will be instrumented with a spy mechanism that counts the number of calls to each context function. The number of calls to each function during the previous FPS interval will be included in the newcontextSpyDatakey of the 'fpsUpdate' event.The Context Spy can be enabled in Example Tests by the
contextSpyboolean URL param. When enabled, a statistical calculation of each context function call will be reported after every FPS statistics summary. Because of this, the option requires that thefpsURL param is also set to true, otherwise only a degradation of performance will occur without any output of the Context Spy data.Example output:
BREAKING CHANGE
This is a breaking change because the 'fpsUpdate' event previously only used a
numberas its payload type, whereas now it is an object with the keysfpsandcontextSpyData. Apps/frameworks that listen for the 'fpsUpdate' event will need to update their handlers.