hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.74k stars 429 forks source link

[Turbo Streams + Flask] Memory leak when page is not in focus (Edge 103) #639

Open danilofuchs opened 2 years ago

danilofuchs commented 2 years ago

Issue Description

Webpage memory consumption is increasing over time, reaching over 3GB if the tab is not in focus, leading to a freeze with an out-of-memory error code.

If page goes back in focus or is refreshed, consumption is stable at 100MB.

Elements are being created and removed every 1 second, but it looks like old elements are not garbage collected when the tab is on background.

(readings from the chromium task manager)

Setup

Turbo-Flask 0.8.0 (Turbo 7.1.0) Flask 2.1.2 Python 3.7.8 Microsoft Edge 103.0.1264.62

Use Case

Web page for monitoring a long running process.

Multiple variables update every 1 second, using turbo.update

turbo.push(turbo.update(
    render_template(
        'content_targets.html',
        targets=monitor.targets,
        metadata=monitor.metadata
     ),
     'targets'
    )
)

This recreates the entire web page every 1 second. On the dev tools, it is possible to see the DOM tree being updated.

Current workaround is to refresh the page every minute if in background:

setInterval(() => {
    if (document.hidden) {
        document.location.reload()
    }
}, 60 * 1000)
tleish commented 2 years ago

Can you share the contents of content_targets.html?

danilofuchs commented 2 years ago

We have a list of 6 targets, updating every value every second.

There are 2 files updated every time. First is a summary card for the target being monitored:

content_targets.html ```html
{% for target in targets %}
{{ target.name }} {{ target.ip }}:{{ target.port }}
{{ target.variant }}
{% if target.lastStatus == "Running" %}
{% else %}
{% endif %}

{{ target.status }} {{ target.timestamp }}
SW Status: {{ target.lastStatus }}
{{ target.SWVersion }}
CPU: {{ target.CpuVersion }}
GPU: {{ target.GpuVersion }}

Voltage output 1 {{ target.AvgVoltage1Monitoring }} V

Current output 1 {{ target.AvgCurrent1Monitoring }} A

Voltage output 2 {{ target.AvgVoltage2Monitoring }} V

Current output 2 {{ target.AvgCurrent2Monitoring }} A

{% endfor %}
```

Second, there is a list of monitored values, composed of ~50 values for each target, totaling 300 distinct table rows:

monitoring.html ```html
{% for target in targets %}
{{ target.name }} {{ target.ip }}:{{ target.port }}
{{ target.variant }}
{% if target.lastStatus == "Running" %}
{% else %}
{% endif %}

{{ target.status }} {{ target.timestamp }}

Variable name Value


{% for name in target.itemIdentifiers %}

{{ name }} {{ target.MonitoringItemsValue[loop.index0] }}


{% endfor %}
{% endfor %}
```
tleish commented 2 years ago

I'm not sure if this is a turbo bug or a MS Edge bug. Does the same thing occur in other browsers? Are MS Edge "Sleeping Tabs" enabled or disabled? Does adjusting Sleeping Tabs settings fix the memory leak?

image

danilofuchs commented 2 years ago

This does not occur on Firefox

Edge 104.0.1293.47 seems to have fixed the problem. Memory grows until ~500MB, than runs garbage collector and caps at 200MB

This is the same with or without Sleeping tabs.

We will run the test over a long period to make sure.