-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
RichText leaks memory when replacing segments #4723
Comments
JFYI,
|
Is this confirmed to be an actual memory leak (IE the memory consumed by the app does not go down after it's idle for awhile)? If not, I wouldn't really call this a leak, it's just that markdown parsing results in a fair amount of allocations and work for the GC. However, there are some future improvements being planned for the internal font caching which should hopefully result in reduced allocations and steady-state memory use once implemented. |
It never goes down. Run this to check yourself: package main
import (
"fmt"
"runtime"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/widget"
"github.com/google/uuid"
)
func main() {
a := app.New()
w := a.NewWindow("Fyne's RichText Memory Leak")
w.Resize(fyne.NewSize(128, 128/1.618))
rt := widget.NewRichText()
go func() {
var m runtime.MemStats
for {
time.Sleep(time.Second)
// Force GC just to make measurements a bit more precise.
runtime.GC()
// Report memory consumption.
runtime.ReadMemStats(&m)
fmt.Printf(
"Sys: %v MiB\tHeapAlloc: %v MiB\tTotalAlloc: %v MiB\tNumGC: %v\n",
m.Sys/1024/1024, m.HeapAlloc/1024/1024, m.TotalAlloc/1024/1024, m.NumGC,
)
}
}()
go func() {
for i := 1; i != 1000000; i++ {
rt.ParseMarkdown(uuid.NewString())
}
}()
w.SetContent(rt)
w.ShowAndRun()
} |
I also noticed this issue while building a chat app, which led me to many markdown updates due to the message timestamp I decided to update on the screen. Upon closer examination, I saw that the RichText's visualCache map does grow indefinitely. However, I didn't quite understand the reason for keeping the cache of previous segments if we are completely changing the content via ParseMarkdown. richmarkdowndebug.mp4Then I decided to change the ParseMarkdown function in widget/markdown.go to clear the cache if it already exists for that RichText:
The memory usage significantly decreased and I was able to watch the GC working (HeapAlloc decreasing after some time). My app was not affected (as far as I can tell). Anyway, I can by no means claim that this is a solution or even that the visualCache causes a memory leak. |
Good find. Looking at the code, the visualCache definitely leaks memory as nothing is ever cleared out of it. The |
Fixed on |
Checklist
Describe the bug
Changing
RichText
content by invokingRichText.ParseMarkdown
leads to linear growth of memory consumption. In the practical case I faced it took gigabytes of RAM in a couple of hours.How to reproduce
To reproduce — call
RichText.ParseMarkdown
many times with different content. Or just use the snippet I attached below.Screenshots
Memory growth (one line per second):
Example code
Fyne version
2.4.4
Go compiler version
1.22.1
Operating system and version
macOS Sonoma 14.4
Additional Information
No response
The text was updated successfully, but these errors were encountered: