Closed georgewsinger closed 3 years ago
We added a ./result/bin/simula_valgrind
wrapper in https://github.com/SimulaVR/Simula/commit/432da3a99c7f5d609f091068618ff3e7cac29bc1 which generates XML output. The results of running this against a Simula launch with one app running:
memnew
/memdelete
in gdwlroots: valgrind_output_memnew _memdelete.bz2new
/delete
in gdwlroots: valgrind_output_new _delete.bz2I added ./result/bin/simula_valkyrie
in https://github.com/SimulaVR/Simula/commit/90f03cdacfa7f367a5c23fb8a3cf70c2cb9d44db, which allows us to help parse these extremely large valgrind output files.
./result/bin/simula_valgrind <name_of_valgrind_output.xml>
We're getting "unexpected character" errors (see above), but the GUI still seems to launch with useful output.
We recently ran valgrind against Simula:
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-origins=yes --keep-stacktraces=alloc-and-free --error-limit=no --num-callers=40 --xml=yes --xml-file=valgrind_output_%p.xml <simula_godot_binary>
generating the following files:
valgrind_output_636031.xml valgrind_output_636568.xml valgrind_output_636622.xml
valgrind_output_636033.xml valgrind_output_636571.xml valgrind_output_636624.xml
valgrind_output_636050_linted.xml valgrind_output_636574.xml valgrind_output_636702.xml
valgrind_output_636050.xml valgrind_output_636580.xml valgrind_output_636704.xml
valgrind_output_636546.xml valgrind_output_636582.xml valgrind_output_636706.xml
valgrind_output_636547.xml valgrind_output_636585.xml valgrind_output_636708.xml
valgrind_output_636548.xml valgrind_output_636588.xml valgrind_output_636710.xml
valgrind_output_636549.xml valgrind_output_636591.xml valgrind_output_636712.xml
valgrind_output_636566.xml valgrind_output_636594.xml valgrind_output_636714.xml
The most interesting two files are valgrind_output_636031.xml
and valgrind_output_636548.xml
, since only these files involve Wlr*
types. These are also the biggest files (about 600MB each in size).
valgrind_output_636031.xml
with valkyrie (see below).A few of these files fail to open at all (all from the first column):
valgrind_output_636033.xml
valgrind_output_636050_linted.xml
valgrind_output_636050.xml
valgrind_output_636548.xml
//\<- This one is importantThe output in these cases is:
$ valkyrie --view-log ./valgrind_output_636033.xml
MainWindow::runTool( tool: 0, proc: 1 )
Valkyrie::runTool( 0, 1)
Segmentation fault (core dumped)
$ valkyrie --view-log valgrind_output_636050.xml
MainWindow::runTool( tool: 0, proc: 1 )
Valkyrie::runTool( 0, 1)
Segmentation fault (core dumped)
$ valkyrie --view-log valgrind_output_636050_linted.xml
MainWindow::runTool( tool: 0, proc: 1 )
Valkyrie::runTool( 0, 1)
Segmentation fault (core dumped)
valkyrie --view-log valgrind_output_636548.xml
MainWindow::runTool( tool: 0, proc: 1 )
Valkyrie::runTool( 0, 1)
Segmentation fault (core dumped)
and the valkyrie GUI opens for a few frames and closes.
For example, here's the result of opening valgrind_output_636031.xml
:
george@UbuntuBox:~/Simula$ ./result/bin/valkyrie --view-log ./valgrind_output_by_process/valgrind_output_636031.xml
MainWindow::runTool( tool: 0, proc: 1 )
Valkyrie::runTool( 0, 1)
===valkyrie:111639=== DEBUG: toolview/vglogview.cpp#102: static VG_ELEM::ElemType VgOutputItem::elemType(QString):
===valkyrie:111639=== Element not found: 'fatal_signal'
===valkyrie:111639===
===valkyrie:111639=== VgLogView::appendNode(): Unrecognised tagname: (fatal_signal)
The worst outcome here though is that we're only able to inspect invalid read/write calls (not actual memory leaks, AFAIK).
Overview. I found the following by simply grepping the valgrind files for Wlr types/calls.
_bind_method
, initialize_class
, create_method_bind
, & register_class
. I'm assuming these are all godot-haskell initialization calls, but maybe they're ongoing calls that are leaking somewhere?WlrKeyboard::_notification
and WlrKeyboard::ensure_keyboard
(even though the keyboard was never pressed, AFAIK, during the actual valgrind trace).from_wlr_surface
, start_xwayland
, from_wlr_xdg_surface
, from_wlr_xdg_toplevel
, WlrXdgToplevel::WlrXdgToplevel(wlr_xdg_toplevel*)
, WlrXdgSurface::WlrXdgSurface(wlr_xdg_surface*)
, WlrXdgShell::handle_new_surface(wl_listener*, void*)
, WlrXdgShell::ensure_wl_global(WaylandDisplay*)
, WlrXdgShell::WlrXdgShell()
. There are also a few calls involving the other Wlr*::_notification
(e.g. WlrSeat
, WlrBackend
, WlrOutput
, WlrXdgShell
, WlrDataDeviceManager
, WlrCompositor
).
from_wlr_surface
?), but I'm afraid they aren't called at a frequency high enough to sustain a constant 2MB/sec heap leak?WlrKeyboard_::notification
void WlrKeyboard::ensure_keyboard() {
//cout << "WlrKeyboard::ensure_keyboard" << endl;
struct xkb_rule_names rules = { 0 };
wlr_keyboard_init(&wlr_keyboard, &keyboard_impl);
// TODO: configure xkb with godot properties?
rules.rules = getenv("XKB_DEFAULT_RULES");
rules.model = getenv("XKB_DEFAULT_MODEL");
rules.layout = getenv("XKB_DEFAULT_LAYOUT");
rules.variant = getenv("XKB_DEFAULT_VARIANT");
rules.options = getenv("XKB_DEFAULT_OPTIONS");
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
assert(context);
struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
assert(keymap);
wlr_keyboard_set_keymap(&wlr_keyboard, keymap);
xkb_keymap_unref(keymap);
xkb_context_unref(context);
wlr_input_device_init(&wlr_input_device, WLR_INPUT_DEVICE_KEYBOARD,
NULL, "Godot", 1, 1);
wlr_input_device.keyboard = &wlr_keyboard;
key.notify = handle_key;
wl_signal_add(&wlr_keyboard.events.key, &key);
modifiers.notify = handle_modifiers;
wl_signal_add(&wlr_keyboard.events.modifiers, &modifiers);
keyboard_init = true;
}
void WlrKeyboard::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
ensure_keyboard();
set_process_input(true);
break;
case NOTIFICATION_EXIT_TREE:
if (keyboard_init) {
wlr_keyboard_destroy(&wlr_keyboard);
}
set_process_input(false);
break;
}
}
WlrSuface::from_wlr_surface
WlrSurface::WlrSurface(struct wlr_surface *surface) {
wlr_log(WLR_DEBUG, "Created surface %p for %p", this, surface);
// TODO: Handle surface destroyed
wlr_surface = surface;
surface->data = this;
new_subsurface.notify = handle_new_subsurface;
wl_signal_add(&wlr_surface->events.new_subsurface,
&new_subsurface);
destroy.notify = handle_destroy;
wl_signal_add(&wlr_surface->events.destroy,
&destroy);
commit.notify = handle_commit;
wl_signal_add(&wlr_surface->events.commit,
&commit);
}
WlrSurface *WlrSurface::from_wlr_surface(struct wlr_surface *surface) {
if (!surface) {
return NULL;
}
if (surface->data) {
auto s = (WlrSurface *)surface->data;
return s;
}
return new WlrSurface(surface);
}
WlrXdgSurface::from_wlr_xdg_surface
WlrXdgToplevel::WlrXdgToplevel(struct wlr_xdg_toplevel *xdg_toplevel) {
wlr_xdg_toplevel = xdg_toplevel;
request_maximize.notify = handle_request_maximize;
wl_signal_add(&wlr_xdg_toplevel->events.request_maximize,
&request_maximize);
request_fullscreen.notify = handle_request_fullscreen;
wl_signal_add(&wlr_xdg_toplevel->events.request_fullscreen,
&request_fullscreen);
request_minimize.notify = handle_request_minimize;
wl_signal_add(&wlr_xdg_toplevel->events.request_minimize,
&request_minimize);
request_move.notify = handle_request_move;
wl_signal_add(&wlr_xdg_toplevel->events.request_move, &request_move);
request_resize.notify = handle_request_resize;
wl_signal_add(&wlr_xdg_toplevel->events.request_resize, &request_resize);
request_show_window_menu.notify = handle_request_show_window_menu;
wl_signal_add(&wlr_xdg_toplevel->events.request_show_window_menu,
&request_show_window_menu);
set_parent.notify = handle_set_parent;
wl_signal_add(&wlr_xdg_toplevel->events.set_parent, &set_parent);
set_title.notify = handle_set_title;
wl_signal_add(&wlr_xdg_toplevel->events.set_title, &set_title);
set_app_id.notify = handle_set_app_id;
wl_signal_add(&wlr_xdg_toplevel->events.set_app_id, &set_app_id);
}
WlrXdgToplevel *WlrXdgToplevel::from_wlr_xdg_toplevel(
struct wlr_xdg_toplevel *xdg_toplevel) {
WlrXdgSurface *surface = (WlrXdgSurface *)xdg_toplevel->base->data;
if (surface->toplevel) {
return surface->toplevel;
}
return new WlrXdgToplevel(xdg_toplevel);
}
WlrXdgSurface::WlrXdgSurface(struct wlr_xdg_surface *xdg_surface) {
wlr_xdg_surface = xdg_surface;
xdg_surface->data = this;
destroy.notify = handle_destroy;
wl_signal_add(&xdg_surface->events.destroy, &destroy);
new_popup.notify = handle_new_popup;
wl_signal_add(&xdg_surface->events.new_popup, &new_popup);
map.notify = handle_map;
wl_signal_add(&xdg_surface->events.map, &map);
unmap.notify = handle_unmap;
wl_signal_add(&xdg_surface->events.unmap, &unmap);
ping_timeout.notify = handle_unmap;
wl_signal_add(&xdg_surface->events.ping_timeout, &ping_timeout);
switch (xdg_surface->role) {
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
toplevel = WlrXdgToplevel::from_wlr_xdg_toplevel(
wlr_xdg_surface->toplevel);
break;
case WLR_XDG_SURFACE_ROLE_POPUP:
popup = WlrXdgPopup::from_wlr_xdg_popup(wlr_xdg_surface->popup);
break;
case WLR_XDG_SURFACE_ROLE_NONE:
assert(0);
break;
}
}
WlrXdgSurface *WlrXdgSurface::from_wlr_xdg_surface(
struct wlr_xdg_surface *xdg_surface) {
if (xdg_surface->data) {
return (WlrXdgSurface *)xdg_surface->data;
}
return new WlrXdgSurface(xdg_surface);
}
WlrXWaylandSurface::from_wlr_xwayland_surface
WlrXWaylandSurface::WlrXWaylandSurface(struct wlr_xwayland_surface *xwayland_surface) {
wlr_xwayland_surface = xwayland_surface;
xwayland_surface->data = this;
wlr_xwayland_surface_ping(xwayland_surface);
destroy.notify = handle_destroy;
wl_signal_add(&xwayland_surface->events.destroy, &destroy);
request_configure.notify = handle_request_configure;
wl_signal_add(&xwayland_surface->events.request_configure, &request_configure);
map.notify = handle_map;
wl_signal_add(&xwayland_surface->events.map, &map);
unmap.notify = handle_unmap;
wl_signal_add(&xwayland_surface->events.unmap, &unmap);
request_maximize.notify = handle_request_maximize;
wl_signal_add(&wlr_xwayland_surface->events.request_maximize, &request_maximize);
request_fullscreen.notify = handle_request_fullscreen;
wl_signal_add(&wlr_xwayland_surface->events.request_fullscreen, &request_fullscreen);
request_move.notify = handle_request_move;
wl_signal_add(&wlr_xwayland_surface->events.request_move, &request_move);
request_resize.notify = handle_request_resize;
wl_signal_add(&wlr_xwayland_surface->events.request_resize, &request_resize);
set_parent.notify = handle_set_parent;
wl_signal_add(&wlr_xwayland_surface->events.set_parent, &set_parent);
}
WlrXWaylandSurface *WlrXWaylandSurface::from_wlr_xwayland_surface(
struct wlr_xwayland_surface *xwayland_surface) {
if (xwayland_surface->data) {
return (WlrXWaylandSurface *)xwayland_surface->data;
}
return new WlrXWaylandSurface(xwayland_surface);
}
@kanetw I'm assuming the following calls are almost certainly not leaking?
_bind_method
initialize_class
create_method_bind
register_class
Only worry about the calls that run more than once or a few times basically.
On Mon, 17 May 2021, 21:01 George Singer, @.***> wrote:
1 Valgrind command
We recently ran valgrind against Simula:
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-origins=yes --keep-stacktraces=alloc-and-free --error-limit=no --num-callers=40 --xml=yes --xml-file=valgrindoutput%p.xml
generating the following files:
valgrind_output_636031.xml valgrind_output_636568.xml valgrind_output_636622.xml valgrind_output_636033.xml valgrind_output_636571.xml valgrind_output_636624.xml valgrind_output_636050_linted.xml valgrind_output_636574.xml valgrind_output_636702.xml valgrind_output_636050.xml valgrind_output_636580.xml valgrind_output_636704.xml valgrind_output_636546.xml valgrind_output_636582.xml valgrind_output_636706.xml valgrind_output_636547.xml valgrind_output_636585.xml valgrind_output_636708.xml valgrind_output_636548.xml valgrind_output_636588.xml valgrind_output_636710.xml valgrind_output_636549.xml valgrind_output_636591.xml valgrind_output_636712.xml valgrind_output_636566.xml valgrind_output_636594.xml valgrind_output_636714.xml
Here is a tarball of these files: 2 Processes 636031 and 636548 are the only two interesting ones
The most interesting two files are valgrind_output_636031.xml and valgrind_output_636548.xml, since only these files involve Wlr* types. These are also the biggest files (about 600MB each in size).
- Our memory leak only occurs when we launch apps, so it's highly likely these types are involved in the leak.
- We are only able to inspect valgrind_output_636031.xml with valkyrie (see below).
3 Valkyrie fails for a few of these files (including 636548)
A few of these files fail to open at all (all from the first column):
- valgrind_output_636033.xml
- valgrind_output_636050_linted.xml
- valgrind_output_636050.xml
- valgrind_output_636548.xml //<- This one is important
The output in these cases is:
$ valkyrie --view-log ./valgrind_output_636033.xml MainWindow::runTool( tool: 0, proc: 1 ) Valkyrie::runTool( 0, 1) Segmentation fault (core dumped)
$ valkyrie --view-log valgrind_output_636050.xml MainWindow::runTool( tool: 0, proc: 1 ) Valkyrie::runTool( 0, 1) Segmentation fault (core dumped)
$ valkyrie --view-log valgrind_output_636050_linted.xml MainWindow::runTool( tool: 0, proc: 1 ) Valkyrie::runTool( 0, 1) Segmentation fault (core dumped)
valkyrie --view-log valgrind_output_636548.xml MainWindow::runTool( tool: 0, proc: 1 ) Valkyrie::runTool( 0, 1) Segmentation fault (core dumped)
and the valkyrie GUI opens for a few frames and closes. 4 Valkyrie opens for the remaining files (including 636031), but with errors and limited viewing ability
For example, here's the result of opening valgrind_output_636031.xml:
george@UbuntuBox:~/Simula$ DISPLAY=:0 ./result/bin/valkyrie --view-log ./valgrind_output_by_process/valgrind_output_636031.xml MainWindow::runTool( tool: 0, proc: 1 ) Valkyrie::runTool( 0, 1) ===valkyrie:111639=== DEBUG: toolview/vglogview.cpp#102: static VG_ELEM::ElemType VgOutputItem::elemType(QString): ===valkyrie:111639=== Element not found: 'fatal_signal' ===valkyrie:111639=== ===valkyrie:111639=== VgLogView::appendNode(): Unrecognised tagname: (fatal_signal)
The worst outcome here though is that we're only able to inspect invalid read/write calls (not actual memory leaks, AFAIK). 5 Potentially leaking Wlr calls
Overview. I found the following by simply grepping the valgrind files for Wlr types/calls.
- There are tons of calls involving _bind_method, initialize_class, create_method_bind, & register_class. I'm assuming these are all godot-haskell initialization calls, but maybe they're ongoing calls that are leaking somewhere?
- There are tons of calls involving WlrKeyboard::_notification and WlrKeyboard::ensure_keyboard (even though the keyboard was never pressed, AFAIK, during the actual valgrind trace).
- There are a some calls involving from_wlr_surface, start_xwayland, from_wlr_xdg_surface, from_wlr_xdg_toplevel, WlrXdgToplevel::WlrXdgToplevel(wlr_xdg_toplevel), WlrXdgSurface::WlrXdgSurface(wlr_xdg_surface), WlrXdgShell::handle_new_surface(wl_listener, void), WlrXdgShell::ensure_wl_global(WaylandDisplay), WlrXdgShell::WlrXdgShell(). There are also a few calls involving the other Wlr::_notification (e.g. WlrSeat, WlrBackend, WlrOutput, WlrXdgShell, WlrDataDeviceManager, WlrCompositor).
- Some of these calls look promising for potential leaks (e.g. from_wlr_surface?), but I'm afraid they aren't called at a frequency high enough to sustain a constant 2MB/sec heap leak?
WlrKeyboard_::notification
void WlrKeyboard::ensure_keyboard() { //cout << "WlrKeyboard::ensure_keyboard" << endl; struct xkb_rule_names rules = { 0 };
wlr_keyboard_init(&wlr_keyboard, &keyboard_impl); // TODO: configure xkb with godot properties? rules.rules = getenv("XKB_DEFAULT_RULES"); rules.model = getenv("XKB_DEFAULT_MODEL"); rules.layout = getenv("XKB_DEFAULT_LAYOUT"); rules.variant = getenv("XKB_DEFAULT_VARIANT"); rules.options = getenv("XKB_DEFAULT_OPTIONS"); struct xkb_context context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(context); struct xkb_keymap keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); assert(keymap); wlr_keyboard_set_keymap(&wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context);
wlr_input_device_init(&wlr_input_device, WLR_INPUT_DEVICE_KEYBOARD, NULL, "Godot", 1, 1); wlr_input_device.keyboard = &wlr_keyboard;
key.notify = handle_key; wl_signal_add(&wlr_keyboard.events.key, &key); modifiers.notify = handle_modifiers; wl_signal_add(&wlr_keyboard.events.modifiers, &modifiers);
keyboard_init = true; }
void WlrKeyboard::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: ensure_keyboard(); set_process_input(true); break; case NOTIFICATION_EXIT_TREE: if (keyboard_init) { wlr_keyboard_destroy(&wlr_keyboard); } set_process_input(false); break; } }
WlrSuface::from_wlr_surface
WlrSurface::WlrSurface(struct wlr_surface *surface) { wlr_log(WLR_DEBUG, "Created surface %p for %p", this, surface); // TODO: Handle surface destroyed wlr_surface = surface; surface->data = this;
new_subsurface.notify = handle_new_subsurface; wl_signal_add(&wlr_surface->events.new_subsurface, &new_subsurface);
destroy.notify = handle_destroy; wl_signal_add(&wlr_surface->events.destroy, &destroy);
commit.notify = handle_commit; wl_signal_add(&wlr_surface->events.commit, &commit);
}
WlrSurface WlrSurface::from_wlr_surface(struct wlr_surface surface) { if (!surface) { return NULL; } if (surface->data) { auto s = (WlrSurface *)surface->data; return s; } return new WlrSurface(surface); }
WlrXdgSurface::from_wlr_xdg_surface
WlrXdgToplevel::WlrXdgToplevel(struct wlr_xdg_toplevel *xdg_toplevel) { wlr_xdg_toplevel = xdg_toplevel; request_maximize.notify = handle_request_maximize; wl_signal_add(&wlr_xdg_toplevel->events.request_maximize, &request_maximize); request_fullscreen.notify = handle_request_fullscreen; wl_signal_add(&wlr_xdg_toplevel->events.request_fullscreen, &request_fullscreen); request_minimize.notify = handle_request_minimize; wl_signal_add(&wlr_xdg_toplevel->events.request_minimize, &request_minimize); request_move.notify = handle_request_move; wl_signal_add(&wlr_xdg_toplevel->events.request_move, &request_move); request_resize.notify = handle_request_resize; wl_signal_add(&wlr_xdg_toplevel->events.request_resize, &request_resize); request_show_window_menu.notify = handle_request_show_window_menu; wl_signal_add(&wlr_xdg_toplevel->events.request_show_window_menu, &request_show_window_menu); set_parent.notify = handle_set_parent; wl_signal_add(&wlr_xdg_toplevel->events.set_parent, &set_parent); set_title.notify = handle_set_title; wl_signal_add(&wlr_xdg_toplevel->events.set_title, &set_title); set_app_id.notify = handle_set_app_id; wl_signal_add(&wlr_xdg_toplevel->events.set_app_id, &set_app_id); }
WlrXdgToplevel WlrXdgToplevel::from_wlr_xdg_toplevel( struct wlr_xdg_toplevel xdg_toplevel) { WlrXdgSurface surface = (WlrXdgSurface )xdg_toplevel->base->data; if (surface->toplevel) { return surface->toplevel; } return new WlrXdgToplevel(xdg_toplevel); }
WlrXdgSurface::WlrXdgSurface(struct wlr_xdg_surface *xdg_surface) { wlr_xdg_surface = xdg_surface; xdg_surface->data = this; destroy.notify = handle_destroy; wl_signal_add(&xdg_surface->events.destroy, &destroy); new_popup.notify = handle_new_popup; wl_signal_add(&xdg_surface->events.new_popup, &new_popup); map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &map); unmap.notify = handle_unmap; wl_signal_add(&xdg_surface->events.unmap, &unmap); ping_timeout.notify = handle_unmap; wl_signal_add(&xdg_surface->events.ping_timeout, &ping_timeout);
switch (xdg_surface->role) { case WLR_XDG_SURFACE_ROLE_TOPLEVEL: toplevel = WlrXdgToplevel::from_wlr_xdg_toplevel( wlr_xdg_surface->toplevel); break; case WLR_XDG_SURFACE_ROLE_POPUP: popup = WlrXdgPopup::from_wlr_xdg_popup(wlr_xdg_surface->popup); break; case WLR_XDG_SURFACE_ROLE_NONE: assert(0); break; } }
WlrXdgSurface WlrXdgSurface::from_wlr_xdg_surface( struct wlr_xdg_surface xdg_surface) { if (xdg_surface->data) { return (WlrXdgSurface *)xdg_surface->data; } return new WlrXdgSurface(xdg_surface); }
WlrXWaylandSurface::from_wlr_xwayland_surface
WlrXWaylandSurface::WlrXWaylandSurface(struct wlr_xwayland_surface *xwayland_surface) { wlr_xwayland_surface = xwayland_surface; xwayland_surface->data = this;
wlr_xwayland_surface_ping(xwayland_surface); destroy.notify = handle_destroy; wl_signal_add(&xwayland_surface->events.destroy, &destroy); request_configure.notify = handle_request_configure; wl_signal_add(&xwayland_surface->events.request_configure, &request_configure); map.notify = handle_map; wl_signal_add(&xwayland_surface->events.map, &map); unmap.notify = handle_unmap; wl_signal_add(&xwayland_surface->events.unmap, &unmap); request_maximize.notify = handle_request_maximize; wl_signal_add(&wlr_xwayland_surface->events.request_maximize, &request_maximize); request_fullscreen.notify = handle_request_fullscreen; wl_signal_add(&wlr_xwayland_surface->events.request_fullscreen, &request_fullscreen); request_move.notify = handle_request_move; wl_signal_add(&wlr_xwayland_surface->events.request_move, &request_move); request_resize.notify = handle_request_resize; wl_signal_add(&wlr_xwayland_surface->events.request_resize, &request_resize);
set_parent.notify = handle_set_parent; wl_signal_add(&wlr_xwayland_surface->events.set_parent, &set_parent); }
WlrXWaylandSurface WlrXWaylandSurface::from_wlr_xwayland_surface( struct wlr_xwayland_surface xwayland_surface) { if (xwayland_surface->data) { return (WlrXWaylandSurface *)xwayland_surface->data; } return new WlrXWaylandSurface(xwayland_surface); }
godot-haskell calls
@KaneTW https://github.com/KaneTW I'm assuming the following calls are almost certainly not leaking?
- _bind_method
- initialize_class
- create_method_bind
- register_class
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/SimulaVR/Simula/issues/126#issuecomment-842557938, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB534J3XY22O45I4YTQSASTTOFRZBANCNFSM43JKMLZA .
@KaneTW
start_xwayland
) I assume are only actually ran once.WlrKeyboard::ensure_keyboard()
look like they leak to me?I attempted to parse these valgrind files without the use of valkyrie or emacs (opening these files on my emacs crashes it).
TLDR: It doesn't seem like any Wlr*
are leaking that badly (certainly nothing on the order of 2MB/sec).
*List of `Wlrcalls.** Here is a list of all of the mentions of
Wlr*` calls in the valgrind files: here.
Leaked blocks/bytes. In the files of interest, we're counting 572,880
leaked bytes/blocks instances:
george@UbuntuBox:~/Simula/valgrind_total_command$ cat valgrind_output_636031.xml valgrind_output_636548.xml | grep -a leaked | wc -l
572880
which show up like this in the *.xml
files:
<leakedbytes>48</leakedbytes>
<leakedblocks>1</leakedblocks>
<leakedbytes>48</leakedbytes>
<leakedblocks>1</leakedblocks>
# ... several thousand lines ...
<leakedblocks>1</leakedblocks>
<leakedbytes>1147120</leakedbytes>
<leakedblocks>1</leakedblocks>
<leakedbytes>1491840</leakedbytes>
<leakedblocks>60</leakedblocks>
<leakedbytes>2621456</leakedbytes>
<leakedblocks>1</leakedblocks>
<leakedbytes>2621456</leakedbytes>
<leakedblocks>1</leakedblocks>
<leakedbytes>2904216</leakedbytes>
<leakedblocks>59</leakedblocks>
<leakedbytes>3604503</leakedbytes>
<leakedblocks>1</leakedblocks>
If we use Wolfram we get 113.632 MB leaked, which is about right (at 2MB/sec memory leakage, that means the valgrind trace was left on for approximately 55 seconds).
*`Wlrcalls near
errors.** Here are the Wlr\* calls which are made near
*Leaked bytes/blocks near `Wlrcalls seem to be really small, so maybe it's not a Wlr leak at all?.** Similar to (3) but now we only look at leaked bytes near/caused by
Wlr*` calls: link.
Parsing this output with Wolfram we get a tiny number of bytes leaked:
So maybe the leak isn't a Wlr one to begin with?
I also just double checked (through code deletion and htop inspection) that the from_wlr_*
and WlrKeyboard::*
calls are not causing leaks. So it's something else in the code.
I threw up a StackOverflow post to see if other people know how to get past my valkyrie XML parsing issues.
@KaneTW fixed a ~0.5MB/sec thunk leak in https://github.com/SimulaVR/Simula/commit/8f4b4cb3bc6bc49d4ab0888886f6e490066ce7ca. The remaining leaks (~1MB/sec) are coming from gdwlroots.
We have heavily mitigated against the remaining leaks in https://github.com/SimulaVR/Simula/commit/848823cc574340610b1861f92a0a201d18f2e0ca. There are still some smaller leaks that will only be possible to fix with our upcoming godot-haskell rewrite.
A basic GHC memory profiling shows that it looks like a thunk buildup:
More data: