The application will output the log content to MultiLineEntry during operation, and the memory occupied by the application will gradually increase when the application is in the foreground, but it can maintain a stable occupation in the background.I would like to know what the problem is?
This is the main function of the application
var conf = &Conf{}
func main() {
go http.ListenAndServe("0.0.0.0:6060", nil)
a := app.New()
a.Settings().SetTheme(&myTheme{})
w := a.NewWindow("forward")
tab := container.NewAppTabs(
container.NewTabItem("data1", WeatherScreen()),
container.NewTabItem("data2", TossScreen()),
//container.NewTabItem("per", PreferenceScreen(w)),
container.NewTabItem("about", widget.NewLabel("Version:1.0")),
)
//tab.SetTabLocation(container.TabLocationLeading)
rootVBox := container.NewVBox(tab, CreateLogs())
w.SetContent(rootVBox)
w.Resize(fyne.NewSize(700, 364))
w.SetMaster()
w.SetFixedSize(true)
resource, _ := fyne.LoadResourceFromPath("Graphicloads-Polygon-Next-2.ico")
a.SetIcon(resource)
if desk, ok := a.(desktop.App); ok {
m := fyne.NewMenu("forward",
fyne.NewMenuItem("show", func() {
w.Show()
},
),
)
//desk.SetSystemTrayIcon(resource)
desk.SetSystemTrayMenu(m)
}
w.SetIcon(resource)
w.SetCloseIntercept(func() {
//hide
w.Hide()
})
w.CenterOnScreen()
InitData()
//longIp := float32(80)
//shortPort := float32(50)
conf = loadConfig()
w.Show()
a.Run()
}
This is the function I use to process the logs
var logFlag = make(chan string, 10)
var cour = 1
var text = binding.NewString()
func CreateLogs() fyne.CanvasObject {
logs := widget.NewEntryWithData(text)
logs.MultiLine = true
logs.Validator = nil
logs.Resize(fyne.NewSize(688, 230))
//update text
go updateLogs(logFlag, logs)
contain := container.NewWithoutLayout(logs)
return contain
}
func updateLogs(l chan string, logs *widget.Entry) {
for {
if d, ok := <-l; ok {
t, _ := text.Get()
text.Set(t + d)
logs.CursorRow = cour
runtime.GC()
}
}
}
func appendLogs(name string, format string, a ...any) {
now := time.Now()
year, month, day := now.Date()
str := fmt.Sprintf(format, a...)
y := strconv.Itoa(year)
var m string
if int(month) >= 10 {
m = strconv.Itoa(int(month))
} else {
m = "0" + strconv.Itoa(int(month))
}
var d string
if day >= 10 {
d = strconv.Itoa(day)
} else {
d = "0" + strconv.Itoa(day)
}
dateHeader := y + "/" + m + "/" + d + " "
hour, min, sec := now.Clock()
var h string
if hour >= 10 {
h = strconv.Itoa(hour)
} else {
h = "0" + strconv.Itoa(hour)
}
var mi string
if min >= 10 {
mi = strconv.Itoa(min)
} else {
mi = "0" + strconv.Itoa(min)
}
var s string
if sec >= 10 {
s = strconv.Itoa(sec)
} else {
s = "0" + strconv.Itoa(sec)
}
timeHeader := h + ":" + mi + ":" + s + " "
header := dateHeader + timeHeader + name + " "
str = header + str + "\n"
cour++
if cour > 50 {
runtime.GC()
cour = 1
text.Set("")
}
logFlag <- str
}
appendLogs is called once every time there is a log to be exported.
I tried to limit the number of log entries and clear the content of the bound data, but this did not stop the memory growth.
if cour > 50 {
runtime.GC()
cour = 1
text.Set("")
}
I also tried commenting out the entire appendLogs, but that didn't solve the problem either.
I want the memory to remain stable while the application is in the foreground.
Adding lines of text to an Entry
will cause performance issues as it currently renders all the content, plus the SetText
must parse all your newlines to lay it out.
To make something handling large data well you might consider List
with a Label
per line, no parsing and also no rendering of items off screen.
A future version of Entry
aims to improve the memory usage, but a single SetText
will always get slow over time due to the parsing requirement.