SimulaVR / Simula

Linux VR Desktop
MIT License
2.97k stars 91 forks source link

Simula exhibiting 2MB/sec heap leak #126

Closed georgewsinger closed 3 years ago

georgewsinger commented 3 years ago

A basic GHC memory profiling shows that it looks like a thunk buildup:

image

More data:

'libGodotHaskellPlugin.so' +RTS '-srts_stats.txt' '-hT' '-N' 
   2,851,642,152 bytes allocated in the heap
     473,478,992 bytes copied during GC
       1,852,496 bytes maximum residency (68 sample(s))
         494,512 bytes maximum slop
              14 MiB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0      2674 colls,  2674 par    4.585s   0.655s     0.0002s    0.0144s
  Gen  1        68 colls,    67 par    0.702s   0.153s     0.0023s    0.0284s

  Parallel GC work balance: 7.16% (serial 0%, perfect 100%)

  TASKS: 23 (2 bound, 20 peak workers (21 total), using -N8)

  SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

  INIT    time    0.001s  (  0.001s elapsed)
  MUT     time   18.818s  ( 19.967s elapsed)
  GC      time    5.287s  (  0.808s elapsed)
  EXIT    time    0.001s  (  0.004s elapsed)
  Total   time   24.107s  ( 20.780s elapsed)

  Alloc rate    151,540,051 bytes per MUT second

  Productivity  78.1% of total user, 96.1% of total elapsed
georgewsinger commented 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:

georgewsinger commented 3 years ago

I 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>

image

We're getting "unexpected character" errors (see above), but the GUI still seems to launch with useful output.

georgewsinger commented 3 years ago

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=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

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).

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):

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$ ./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.

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 I'm assuming the following calls are almost certainly not leaking?

KaneTW commented 3 years ago

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)

https://camo.githubusercontent.com/e061ba8d645923341817066e699c5240b12fe94712cdce6d6d9c414a98cd16ab/68747470733a2f2f7777772e776f6c6672616d636c6f75642e636f6d2f6f626a2f67656f7267652e772e73696e6765722f627573696e6573732f706e672f32332e706e67

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 .

georgewsinger commented 3 years ago

@KaneTW

georgewsinger commented 3 years ago

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).

  1. *List of `Wlrcalls.** Here is a list of all of the mentions ofWlr*` calls in the valgrind files: here.

  2. 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).

  3. *`Wlrcalls nearerrors.** Here are the Wlr\* calls which are made near..` instances: . Many of these were already discussed above.

  4. *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 byWlr*` 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.

georgewsinger commented 3 years ago

I threw up a StackOverflow post to see if other people know how to get past my valkyrie XML parsing issues.

georgewsinger commented 3 years ago

@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.

georgewsinger commented 3 years ago

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.