【问题标题】:Why this simple GTK3 application consumes so much memory?为什么这个简单的 GTK3 应用程序会消耗这么多内存?
【发布时间】:2017-06-26 19:43:43
【问题描述】:

我创建了一个简单的应用程序,它只创建和显示空的 50x50 窗口,但它已经消耗了 20MB 的内存。我的目标是低内存设备,所以每一兆字节都很重要。是什么导致 GTK 消耗所有内存?是否可以减少内存使用量?

这是程序的完整源代码:

#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;
}

这是我编译的:

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

这是产生的内存使用情况:

$ 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 以 KB 为单位测量内存使用情况,即 20996KB 或 ~21MB)

我在 linux 4.11.6、x86_64 上使用 gtk3 版本 3.22.16。

问题背景:目标系统是内存相对较低的 PC(200-400 MB 内存)。应用程序是该 PC 上类似信息亭的界面,具有相对复杂的 GUI 结构(许多页面和可能的交互)。而且我宁愿避免手动重新实现所有 GUI 逻辑(在较低级别的库之上),所以我正在寻找更高级别的东西 - 似乎该空间中只有 GTK 和 Qt(Qt 是只能从 C++ 中使用,这很痛苦)。

【问题讨论】:

  • 您在什么系统上测量它? (处理器和操作系统)
  • @BasileStarynkevitch - ArchLinux,x64,linux 4.11。
  • 什么是x64(你的意思是x86-64还是amd64)?请编辑您的问题以改进它。
  • @BasileStarynkevitch - 完成。我的意思是 x86_64,当然(x86_64 和 amd64 之间有区别吗?我认为这是同一事物的两个名称)
  • 确实 x86-64 和 amd64 几乎是一回事(对于用户端代码也完全相同)。但也有 x32(我从未听说过 x64)

标签: c gtk gtk3


【解决方案1】:

我在后台运行了您的程序(使用-O1 进行了优化),而不是使用pmap(1) 来观察它的(虚拟)内存映射。它在 Debian/Sid/x86-64 上的 349 个内存段中消耗 335752K(即 335Mbytes)。加载了 77 个不同的共享库。顺便说一句,一旦您使用文本和字体,它们也会进入虚拟地址空间。而ps -FC 为SZ 提供了大约 84Mb,为RSS 提供了 21Mb(也可以尝试使用pmap -x 获取 RSS 详细信息)。

您应该在您自己的(目标)系统上使用pmap,并就消耗内存的内容得出自己的结论。如果pmap 不可用且进程的pid 为1234,请参阅/proc/1234/maps(提供与pmap 相同的 信息并由pmap 解析),请阅读proc(5)

顺便说一句,我对如此高的消费并不感到惊讶。多考虑一下 GUI 使用的所有隐含资源(通过研究 pmap 的输出或使用 strace(1) ...,您会猜到这一点)。另请参阅this answer 并按照我在此处提供的链接进行操作。我的观点是,您实际上需要 1 GB(或至少一半)的 RAM(就像大多数 RaspberryPIs 一样)来运行现代 GUI 工具包,如 Qt 或 GTK。请注意,如今 1 GB 的 RAM 真的很便宜,因此您的公司可能需要销售数百万台设备才能支付数年的额外开发工作,而这些工作仅需要数百兆字节。

(也许您最好使用较低级别的东西,例如 libsdl 或 libX11,但请参阅 this)

所以每一兆字节都很重要

那么你就不需要一个成熟的 GUI 工具包(或者你应该买一个更强大的硬件和一个千兆字节的 RAM)。您可以只针对原始Wayland(或X11)display server(以多年的开发努力为代价,或者接受一个不太复杂的GUI)。顺便说一句,QT(也许还有 GTK)有专门的嵌入式 - 或帧缓冲 - 变体(这可能会稍微减少资源消耗)。

PS。我猜你的操作系统是一些 Linux 变体;我建议阅读一些教科书,例如 Operating Systems : Three Easy Pieces(可免费合法下载),以更好地了解操作系统的工作原理。

【讨论】:

  • 那么所有 20Mb 内存都来自大量正在加载的库?由于内核懒于加载二进制文件,大部分 335Mb 都没有加载?
  • 在您自己的系统上使用pmap 或/proc/1234/maps
  • 我做到了,得到的结果与你的相似。我只是不精通内核内存管理——我目前的理解是它内存映射这些共享库而不是立即将它们加载到内存中(因此我在 ps 输出中只看到 20Mb 而不是 335Mb)。对吗?
  • 我没有观察到ps 的数字如此之低。你具体用了什么命令?
  • 一个有用的补充 - pmap -x 1234 提供每个段的 RSS 大小以及总大小 - 对于查看实际加载的功能非常有帮助。
【解决方案2】:

在声称您的进程占用大量 RAM 之前,您应该回答以下问题:

  1. 添加更多小部件时,RAM 量会增加多少?内存成本很可能是 20 MB + 0.1 MB*k,其中 k 是小部件的数量。
  2. 除了 GUI 之外,您还有多少进程。如果每个小部件的成本低于 0.1 MB(我相信只要你不加载大图像),你可以拥有 1000 个小部件没有任何问题,只要你不运行任何需要大量 RAM 的东西.

此外,由于您的目标系统内存小于 1 gig,因此请调查在 32 位模式下运行的可能性以及该环境中的内存使用情况。这将使每个指针的大小减少 2 倍。这主要影响指针繁重的应用程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-30
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    相关资源
    最近更新 更多