I have problems with memory leaks, so i did the following test code.
#!/usr/bin/cjs
"use strict";
import Gtk from 'gi://Gtk?version=3.0';
Gtk.init (null);
const window= new Gtk.Window ();
let buttons=[], button, box=new Gtk.Box ({ orientation:1}), remove=true;
function construct_buttons ()
{
for (let i=0;i<500;i++)
{
button=new Gtk.Button ({label:"hello"});
box.add (button);
buttons.push (button);
}
}
setInterval (function ()
{
if (remove)
{
for (let i=0;i<500;i++) buttons[i].destroy ();
buttons=[], button=null;
}
else
{
construct_buttons ();
window.show_all ();
}
remove=!remove;
}, 2000);
construct_buttons ();
window.add(box);
window.set_title ("Test");
window.connect ('destroy', () => { Gtk.main_quit (); });
window.set_size_request (740, 600);
window.show_all ();
Gtk.main ();
I construct 500 buttons and add it to a box. After 2 seconds, i destroy them with Gtk.widget.destroy() and release the reference array buttons=[], button=null, and after 2 seconds i construct them again and so on.
Doing this for a while, my memory grows from 17MiB over 50 MiB. Then i stopped it. I cant figure out, what im doing wrong. Ive the same problem with a larger application. This is only a small example for testing.
I also tried instead of destroy. Gtk.widget.remove (widget), and let cjs destroy it, but here also the memory grows.
I've cjs version 6.0.0
I analyzed the original program with the heapgraph tool. After removing the 500 buttons, they are visible in the heap dump, but marked as "unreachable". So they are not leaking, they will just be removed in the next garbage collection.
The problem seems to be that the garbage collector is not being triggered. This is probably the known issue https://gitlab.gnome.org/GNOME/gjs/-/issues/52. For now, you can trigger garbage collection manually by adding imports.system.gc()
after destroying the buttons and nulling out the references. If I add that line to the original script, the memory usage never goes above 19 MB even creating buttons twice as fast and running for 10 minutes.