Skip to content

unexpected memory behaviour when relying on runtime.SetFinalizer vs explicit Close #181

Open
@timruffles

Description

@timruffles

Currently, unless Go GC is frequent, the finalizers may not run, and thus the sitter C types will not be freed. Critically, if the bulk of a program's allocations comes from tree sitter, the process can use huge amounts of memory but Go GC won't run as the Go heap isn't growing. Here's a test case that demonstrates this nuance in runtime.SetFinalizer: https://gist.github.com/timruffles/48bfa3bd5a625d80e7c73d0eacfc8335

Suggestion: update the documentation to recommend people Close() treesitter types where possible, to avoid unexpected memory consumption. The finalizer can remain as a backstop, the pattern recommended in this comment from a go maintainer. Other Go common APIs make use of the defer foo.Close() pattern - e.g. files, HTTP responses - so it doesn't appear to me be an undue burden for users. I believe this will remain the more reliable approach even after runtime.AddCleanup is introduced, deprecating runtime.SetFinalizer, as it will have same behaviour as in the test case above.

This isn't something that'll become immediately obvious in one-shot use-cases of treesitter, but becomes more problematic for long-lived use cases, e.g. editors, LSP servers.

In any case, food for thought, and thanks for go-tree-sitter! 🙌

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions