Skip to content
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

Improve performance of inserting blocks into stacks. #6130

Closed
BeksOmega opened this issue Apr 29, 2022 · 3 comments · Fixed by #6851
Closed

Improve performance of inserting blocks into stacks. #6130

BeksOmega opened this issue Apr 29, 2022 · 3 comments · Fixed by #6851

Comments

@BeksOmega
Copy link
Collaborator

BeksOmega commented Apr 29, 2022

Describe the bug

Current performance on 7eebd78:
Screenshot 2022-04-29 9 27 37 AM

Time to execute endDrag = ~52 ms averaged over 5 trials.

Convert the following txt file to a json file and then load it into your Chrome Dev Tools to view the results:
inserting-1.txt

To Reproduce

Steps to reproduce the behavior:

  1. Go to the playground.
  2. Load the following JSON:
{
  "blocks": {
    "languageVersion": 0,
    "blocks": [
      {
        "type": "controls_if",
        "inputs": {
          "DO0": {
            "block": {
              "type": "controls_if"
            }
          }
        }
      },
      {
        "type": "controls_if"
      }
    ]
  }
}
  1. Go to the performance tab of the chrome devtools.

  2. Enable recording screenshots.

  3. Set CPU Throttling to 6x.

  4. Start a recording.

  5. Insert the single block into the stack of two blocks so that it looks like this:
    image

  6. Stop the recording.

Expected behavior

Ideally, we wouldn't drop frames when inserting blocks. For this to be achieved, inserting needs to complete within 10ms.

Additional context

It looks like hidePreview_ is doing a lot of work (~22ms), and triggering a lot of re-renders I'm hoping that can be cleaned up.

Similarly with connect (~16ms).

This one is going to take some more digging though.

@BeksOmega BeksOmega added issue: triage Issues awaiting triage by a Blockly team member component: performance and removed issue: triage Issues awaiting triage by a Blockly team member labels Apr 29, 2022
@BeksOmega BeksOmega added this to the Bug Bash Backlog milestone Apr 29, 2022
@BeksOmega
Copy link
Collaborator Author

So after some work on this, imo removing the extra render calls needs to be more of a project (with an actual design doc and whatnot). Currently our only way to delay/remove some of these render calls is to set block.rendered = false and block.rendered = true which is error prone, and has historically caused us problems as documented in #4288

Also going to link this to #5375 as refactoring insertion markers will have to take into account when we trigger renders.

@BeksOmega
Copy link
Collaborator Author

To clarify my previous comment: When we're inserting a block, we're actually "rendering" a lot of "stages" of connecting the blocks that never get drawn to the screen. If you use breakpoints you can step through and see them.

After first "dropping" the block:
Screenshot 2022-05-03 2 27 05 PM

Disconnecting the child from the insertion marker:
Screenshot 2022-05-03 2 27 51 PM

Connecting the child to the surrounding parent parent:
Screenshot 2022-05-03 2 28 02 PM

Disconnecting the child from the parent again:
Screenshot 2022-05-03 2 28 22 PM

Connecting the block we dropped to the parent and the child: <-- This is the only thing that actually gets drawn to the screen
Screenshot 2022-05-03 2 28 44 PM

So if we could prevent those first 4 render calls, it would gain us a lot of efficiency. But as mentioned in the previous comment, our current way of doing that isn't very maintainable.

@BeksOmega BeksOmega self-assigned this Jan 18, 2023
@BeksOmega
Copy link
Collaborator Author

So I dug into eliminating the duplicate renders, and it's a bit buggy, but I got some really promising efficiency improvements! ~5x faster for dragging JS spaghetti blocks.

What I'm doing is creating a tree of blocks that need to be rerendered (so for each leaf block that needs to be rerendered, it also adds all of that leaf's parents). Then inside a requestionAnimationFrame callback I'm rerendering all of the blocks depth-first (so all children get rerendered first, which is necessary for the parents to properly render).

Additionally, I added a delay to the bringToFront call in the insertion marker manager, which really improves performance because it means we don't have to do so many style/layout calculations immediately.

Changes are on https://github.com/BeksOmega/blockly/tree/exp/render-queue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant