Skip to content

timegraph views lose some content if many are opened #1196

@marcdumais-work

Description

@marcdumais-work

Bug Description:

It might be more precise to talk about PIXI-created canvas objects getting lost - not all of them are timegraph views.

When opening a few traces that have a couple of timegraph views, or several traces with some views opened, one will notice the following warning in the devtools console:

time-graph-container.ts:39 WARNING: Too many active WebGL contexts. Oldest context will be lost.

Some BG info I quickly gathered:

The affected code is from timeline-chart, file time-graph-container.ts::

export class TimeGraphContainer {
[...]
   constructor(protected config: TimeGraphContainerOptions, [...]
      let canvas: HTMLCanvasElement
      if (!extCanvas) {
          canvas = document.createElement('canvas');
      [...]
      const noWebgl2 = !PIXI.utils.isWebGLSupported() || !canvas.getContext('webgl2');
      [...]

There, timeline-chart, is creating a PIXI canvas, using if available a webgl2 context from the browser. So long WebGL is supported and the browser is able to provide such a context, it's good - it should make canvas operations faster by using hardware acceleration.

Such a canvas seems to be created when:

  • a timeline view is opened for a given trace. This triggers 2 canvas being created: one focusContainer and one for the timeline char itself
  • when a trace is opened and any graphical view is opened other than the default "Overview". This allocates 2 PIXI canvas (when creating elements timegraph-axis and time-navigator). These are garbage-collected if all views other than "Overview" are closed for that trace.

But there seems to be a couple of problems with this, in situations where WebGL is supported:

  • canvas.getContext('webgl2') always succeeds (at least on Chrome/Electron?):
    • if the browser has run out of WebGL contexts (as per its limit), it will "free" an "old" so it can allocate the new requested one. The code above then does not work as intended, apparently expecting that the call to canvas.getContext('webgl2') would return e.g. an undefined value when no WebGL context is available, permitting it to fallback to an un-accelerated canvas. Instead, a WebGL context, previously allocated to another trace viewer canvas, was freed under-the-table by the browser, resulting in a DOM element that can't be found (a couple of them in this screenshot):
      Image

This stackoverflow contains some suggestions that may be interesting to investigate (not sure if they would be practical in our case):
https://stackoverflow.com/questions/59140439/allowing-more-webgl-contexts

Another way might be to count the number of canvas we allocate (and decrement when they get de-allocated) and after a past a certain number, we do not request a WebGL context for a new canvas.

Some related material here, though not exactly the suggestion above:
https://stackoverflow.com/questions/61277222/how-to-determine-number-of-active-webgl-contexts

Steps to Reproduce:

  1. Open a trace, then open a couple of views related to timeline (resources status, IRQ Analisis - scenarios, ...)
  2. Open the devtools and watch for a warning in the console: "WARNING: Too many active WebGL contexts. Oldest context will be lost."
  3. Repeat 1,2 until you see the warning
  4. Once the warning is displayed, go back to the first opened trace and confirm that one or more of its canvas is not an empty element (white with sad face icon in upper left corner)

Additional Information

  • Operating System:
  • Theia Version:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions