Skip to content

Memory is leaked when a component is updated - Simple Reproduction #473

@sschultze

Description

@sschultze

Describe the bug

Memory is leaked when a component is updated.

My Electron (happens in Chrome also, see below!) application has a progress display (status text showing transferred bytes, progress bar) which updates very often. As Electron has the V8 Memory Cage enabled since version 21, limiting the memory to a few gigabytes (they say 4 GB, but it is 3 GB in my tests), the application frontend goes away after a while (leaving an empty BrowserWindow).

After spending a lot of time tracking down this issue, I was able write a simple reproduction - see below - which fills up the memory very fast in Chrome (see Chrome DevTools -> Memory).

To Reproduce

Use a current version of Chrome.

import { render, useState } from 'preact/compat';

// The only purpose of ChildComponent is to create a complex tree, eating up memory fast.

interface ChildComponentProps {
    readonly level: number;
}

function ChildComponent({ level }: ChildComponentProps) {
    return (
        <div>
            <div>{new Date().valueOf().toString()}</div>
            {level < 4 && Array(3).fill(0).map((_, index) => (
                <ChildComponent key={index} level={level + 1} />
            ))}
        </div>
    );
}

function RootComponent() {
    const [counter, setCounter] = useState(0);
    setTimeout(() => setCounter(counter + 1), 0); // simply force updating all the time
    return (
        <div>
            <span>{counter.toString()}</span>
            <div style={{ display: 'none' }}>
                <ChildComponent level={0} />
            </div>
        </div>
    );
}

const rootElement = document.getElementById('root');
render(<RootComponent />, rootElement!);

Expected behavior

Memory usage should remain quite constant. It should definitely not lead to an out-of-memory error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions