2

I created a simple application that only creates and displays empty 50x50 window, but it already consumes 20MB of memory. I am targeting low-memory devices, so each megabyte really counts. What causes GTK to consume all that memory? Is it possible to reduce memory usage?

Here's the complete source code for the program:

#include <gtk/gtk.h>
int main(int argc, char* argv[]) {
  gtk_init(&argc, &argv);

  GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DOCK);
  gtk_window_set_default_size(GTK_WINDOW(window), 50, 50);
  gtk_window_move(GTK_WINDOW(window), 50, 50);

  gtk_widget_show_all(window);
  gtk_main();
  return 0;
}

Here's what I compile it with:

gcc -std=gnu99 -Wall -o example main.c $(pkg-config --cflags --libs gtk+-3.0)

And here's the resulting memory usage:

$ ps -FC example
UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
platon    4214 11052  7 84812 20996   1 16:13 pts/5    00:00:00 ./example

(ps measures memory usage in KB, so that's 20996KB or ~21MB)

I'm using gtk3 version 3.22.16, on linux 4.11.6, x86_64.

Problem context: target system is relatively low-memory PC (200-400 MB of memory). Application is kiosk-like interface on that PC, with relatively complex GUI structure (many pages and possible interactions). And I would have preferred to avoid re-implementing all the GUI logic manually (on top of lower-level libraries), so I was looking for something higher-level - and it seems there is only GTK and Qt in that space (Qt is usable only from C++, which is a pain).

liberforce
  • 11,189
  • 37
  • 48
Rogach
  • 26,050
  • 21
  • 93
  • 172
  • On what system are you measuring that? (processor and operating system) – Basile Starynkevitch Jun 24 '17 at 13:48
  • @BasileStarynkevitch - ArchLinux, x64, linux 4.11. – Rogach Jun 24 '17 at 13:50
  • What is x64 (do you mean x86-64 or amd64)? Please **edit your question** to improve it. – Basile Starynkevitch Jun 24 '17 at 13:51
  • @BasileStarynkevitch - Done. I meant x86_64, of course (is there a difference between x86_64 and amd64? I assumed those were two names for the same thing) – Rogach Jun 24 '17 at 13:54
  • Indeed x86-64 and amd64 are nearly the same thing (and exactly the same for user-land code). But there is also x32 (and I never heard of x64) – Basile Starynkevitch Jun 24 '17 at 13:55
  • Why do you use GTK3 and what exactly is the target system? Please improve your answer again. Also what is the motivation and what kind of application do you want to develop? – Basile Starynkevitch Jun 24 '17 at 14:05
  • Your question looks a lot like some [XY problem](http://xyproblem.info), or you are asking a too broad or different question. You really should motivate your question and tell a lot more about your application – Basile Starynkevitch Jun 24 '17 at 14:19
  • @BasileStarynkevitch - Target system is relatively low-memory PC (200-400 Mb of memory). Application is kiosk-like interface on that PC, with relatively complex GUI structure (many pages and possible interactions). And I would have preferred to avoid re-implementing all the GUI logic manually (on top of lower-level libraries), so I was looking for something higher-level - and it seems there is only GTK and QT in that space (QT is usable only from C++, which is a pain). – Rogach Jun 24 '17 at 14:30
  • As suggested by Basile Starynkevitch, take a look at a lightweight GUI toolkit, FLTK comes to mind but there are others such libui and nuklear. Still, FLTK's hello world consumes ~10MiB for me, I don't know if can get less with the same level of abstraction. – AndreLDM Jun 26 '17 at 20:04

2 Answers2

2

I ran your program (optimized with -O1) in the background, than used pmap(1) to observe its (virtual) memory map. It consumes 335752K (i.e. 335Mbytes) in 349 memory segments, on Debian/Sid/x86-64. 77 different shared libraries are loaded. BTW, as soon as you use texts and fonts, they also go into the virtual address space. And ps -FC gives about 84Mb for SZ and 21Mb for RSS (try also, as commented, with pmap -x, to get RSS details).

You should use pmap on your own (target) system and get your own conclusions about what is consuming memory. If pmap is not available and the process has pid 1234, see /proc/1234/maps (giving the same information as pmap and parsed by pmap), read proc(5)

BTW I am not surprised by such a high consumption. Think a bit more about all the implied resources used by GUIs (and you'll guess that by studying the output of pmap, or using strace(1) ...). See also this answer and follow the links I gave there. My opinion is that you need in practice a gigabyte (or at least half of it) of RAM (like on most RaspberryPIs) to run modern GUI toolkits like Qt or GTK. Notice that today a gigabyte of RAM is really cheap, so your company may need to sell millions of devices to pay up the years of additional development work needed to fit into only a few hundred megabytes.

(Perhaps you'll better use lower level things like libsdl, or libX11 but see this)

so each megabyte really counts

Then you don't want a full-fledged GUI toolkit (or you should afford a more powerful hardware with a gigabyte of RAM). You could target just a raw Wayland (or X11) display server (at the expense of many years of development efforts, or by accepting a much less sophisticated GUI). BTW QT (and perhaps also GTK) have specialized embedded -or framebuffer- variants (which could be slightly less resource consuming).

PS. I guess your OS is some Linux variant; I recommend reading some textbook like Operating Systems : Three Easy Pieces (freely and legally downloadable) to get a better picture about how an OS works.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • So all that 20Mb memory comes from lots of libraries being loaded? And most of those 335Mb are not loaded due to kernel being lazy about loading binaries? – Rogach Jun 24 '17 at 13:42
  • Use `pmap` or `/proc/1234/maps` on your own system – Basile Starynkevitch Jun 24 '17 at 13:45
  • I did that, got results similar to yours. I'm just not well versed in kernel memory management - my current understanding is that it memory-maps those shared libraries instead of loading them into memory immediately (thus I only see 20Mb instead of 335Mb in ps output). Is that correct? – Rogach Jun 24 '17 at 13:52
  • I'm not observing such a low figure with `ps`. What exact command did you use? – Basile Starynkevitch Jun 24 '17 at 13:53
  • `ps -FC example`, in RSS section (vitrual memory is really 339Mb, but that does not contribute to actual memory pressure). – Rogach Jun 24 '17 at 13:55
  • 1
    One useful additon - `pmap -x 1234` gives RSS size for each segment alongside total size - very helpful for seeing what functionality was actually loaded. – Rogach Jun 24 '17 at 14:07
  • libsdl is even worse - it used up 31Mb of RSS, and 224Mb of virtual memory for the same task. – Rogach Jun 24 '17 at 14:12
2

Before claiming that your process eats much RAM you should answer the following questions:

  1. How much would the amount of RAM increase when adding more widgets? It is likely that the memory cost is something like 20 MB + 0.1 MB*k, where k is the number of widgets.
  2. How many processes do you have besides your GUI. If the cost per widget is less than 0.1 MB (I believe it is as long as you do not load huge images), you can have 1000 widgets without any problems, as long as you do not run anything else that takes a lot of RAM.

Also, since you target a system with less than 1 gig of ram, investigate the possibility to run in 32 bit mode and the memory usage in that environment. This will reduce the size of each pointer with a factor of 2. This mainly affects applications that are pointer-heavy.

user877329
  • 6,717
  • 8
  • 46
  • 88