Всем привет! Наша команда разрабатывает IDE для работы с API TestMace. В одной из наших предыдущих статей читатели указывали на непомерно большое потребление памяти electron-приложений. Что ж, настало время цифр :) В данной статье автор оценивает потребление памяти однооконных приложений, написанных с использованием различных тулкитов. Приятного чтения!


Находясь в поисках идеального набора инструментов для создания GUI, я решил измерить объём занимаемой ими памяти.


По сути, я хотел выяснить, какой из них требует наименьшее количество памяти для программы, состоящей из одного пустого окна. В этой статье я расскажу о полученных результатах.



Дисклеймер


В данной статье приводятся данные о занимаемой программой памяти при использовании различных инструментов, фреймворков и библиотек для создания GUI на Linux. Все измерения сделаны на одном и том же компьютере с Ubuntu 19.04 (Disco Dingo) x86_64 с помощью программы Ksysguard, предоставляющей данные о потребляемой приложениями собственной памяти. Я не переустанавливал систему специально для проведения теста. Он был выполнен на моей повидавшей виды Ubuntu, на которой уже были установлены разного рода пакеты, что могло повлиять/исказить результаты.


Для некоторых инструментов я даже добавил измерения, полученные на Windows 10, которые вряд ли можно сравнивать с линуксовскими, но посмотреть интересно.


Хочу заметить, что мои измерения не представляют научной ценности. Имея другие исходные данные, вы можете получить совершенно другие результаты.



Не так просто, как кажется


Так что же нам необходимо измерить? Виртуальную память (VSZ)? Резидентная память (RSS)? Собственная RSS? Разделяемая RSS?


Если коротко, то... я считаю, что при сравнении двух одинаковых программ, разработанных с использованием разных наборов инструментов, правильнее всего будет измерить объем занимаемой процессом собственной памяти с smaps. Ksysguard использует smaps при выводе подробной информации о памяти. Однако с самого начала в своём эксперименте я использовал данные из панели потребления RAM по умолчанию, и только потом мне стало известно, что smaps дают более точные цифры. В целях обеспечения согласованности данных я использовал информацию из дефолтной панели RAM для всех представленных в списке инструментов, хотя, скорее всего, при использовании интерфейса с подробным описанием потребления памяти можно было бы видеть аналогичную ситуацию.


Если подробнее, то... в данной статье мне не хватило бы места на уроки по управлению памятью в Linux, да и к тому же уже существует множество достойных материалов на эту тему: ELC: How much memory are applications really using?, The /proc Filesystem, proc — process information pseudo-filesystem, Linux Memory Management Overview, Memory Management


Список инструментов и их показатели памяти


Ни слова больше. Вот мои результаты:


GUI тулкит Собственная память (MB) Замечания
xcb 0.132
xlib 0.156
nuklear (rawfb) 0.624 не увеличивает потребляемую Xorg память
xforms 0.765
WINAPI (Win10) 1.00 на Windows 10
dlib 1.10
SDL2 (without opengl) 1.10
GDK 1.20
turbo vision 1.30 TUI
nana 1.40
Motif 1.50
FLTK 1.70
MSEGui 2.04
FOX 2.20
nuklear (x11) 2.20 0,4 Мб + 1,8 Мб памяти Xorg
WINAPI (WINE) 2.30
LCL (customdrawn) 2.50
Gtk+2 2.80
wxX11 3.00 не готов к использованию в production
libui 4.00
LCL (Gtk) 4.50
Gtk+3 5.00
wxGtk3 6.00
EFL 7.20
GLFW 9.00
JUCE 10.00 бинарник Projucer, окно не пустое
Sciter 10.00 около 10 Мб, отсутствует Linux Scapp
LCUI 11.00
GLUI 12.50
SFML 13.20
nanogui 14.00
SDL 14.00
U++ 14.00
Agar 15.00
Dear ImGUI (SDL) 15.30
GuiLite 15.80
Dear ImGUI (SDL/Vulkan) 16.50
Mono WinForms 16.564 на Windows 10
Qt 17.00
Ultralight 20.00
revery 23.50
Java Swing 59.30 OpenJDK 12
electron 74.60
JavaFX 80.00 OpenJDK 12
horus_ui 94.00
Flutter Desktop 98.00 upd: на ранних стадиях разработки!
Boost.UI - использует wxWidgets
CEGUI - как это вообще собрать? :(?
IUP - схож с wxWdigets, использует Gtk+ на Linux
Lgi - использует Gtk+ 2
MiniGUI - не удалось выполнить сборку
morda - не удалось выполнить сборку
SFGUI - использует SFML
TGUI - использует SFML
Verdigris - использует Qt


Я был удивлен прожорливостью Flutter, учитывая, что он изначально задумывался как фреймворк для создания GUI мобильных устройств.

UPD (мои благодарности kirbyfan64sos): Flutter Desktop всё еще находится на ранних стадиях разработки, и все сборки являются отладочными. Это означает, что все профайлеры (вроде Observatory) активны, все утверждения отладки включены, а компилятор AoT отключён. Будет интересно перепроверить данные с использованием релизной сборки.


Не скажу, что меня поразили показатели Electron.


Вот с HorusUI я ожидал примерной цифры в 20 Мб, т. к. он использует OpenGL и режим немедленной отрисовки GUI. Не понимаю, почему цифра вышла больше.


Java-фреймворки Swing и JavaFX тоже показали интересные результаты. Они оба крайне ненасытны, и если вы не уверены, какой из них подошел бы для вашего нового Java-проекта, то кажется разумным остановить свой выбор на более удобном и современном фреймворке JavaFX, хотя и придется отсыпать ему чуть больше памяти. Но если память у вас на вес золота, то, конечно, выбирайте Swing.


Qt тоже показал весьма занятные цифры и оказался намного прожорливее большинства других популярных инструментов. Стоит заметить, что большая часть занимаемой им памяти — это объем, потребляемый драйвером amdgpu, установленным в моей системе. Может, это потому, что буферы OpenGL сохраняются локально. То же самое можно видеть с SDL2: программа без OpenGL потребляет 1,1 Мб, а с ним — целых 14 Мб.


WxWidgets и LCL заняли хорошие позиции в этом сравнении. Несмотря на то, что они представляют собой обертки над другими инструментами для GUI, затраты ресурсов у них минимальны. Мне импонирует мысль о возможности перевода бекенда с Gtk+, например, на Qt, тем самым гарантируя независимость от инструментов.


Также выделю Nuklear, просто потому, что, как мне кажется, у него очень крутой режим немедленной отрисовки GUI. Если вас не смущает использование «сырого» X11 фреймбуфера, ваше однооконное приложение будет занимать всего 0,624 Мб, что выглядит весьма впечатляюще.


Заключение


Если вы надеялись увидеть здесь какие-то обобщенные выводы, то, боюсь, я вынужден вас разочаровать.

Комментарии (33)


  1. psFitz
    20.08.2019 11:22

    не ожидал, что электрон обойдет javafx


  1. kekekeks
    20.08.2019 11:30
    +1

    А это был hello world или сколько-нибудь вменяемое приложение?


    1. dimansny Автор
      20.08.2019 11:38

      В качестве приложения было выбрано обычное пустое окно


      1. kekekeks
        20.08.2019 11:53
        +3

        Ну то есть это вообще никак не показывает потребление памяти тулкитом, только его базовый footprint. Увы, исследование ни о чём. На той же виртуализации списков (или её отсутствии) разница может быть на порядки, причём как по потреблению памяти, так и по быстродействию.


        1. dimansny Автор
          20.08.2019 12:08

          Согласен, данное исследование носит весьма синтетический характер. С другой стороны, написание реального приложения для все перечисленных платформ — труд весьма кропотливый с одной стороны, с другой стороны объем данного приложения должен быть весьма большим, чтобы убрать синтетичность. Даже озвученный вами кейс с виртуализацией «выстреливает» далеко не всегда, да и к тому же на том же electron-е (не уверен, но я надеюсь и в других популярных GUI фреймворках) это легко реализуется.
          Ну и в конце концов сам автор предупреждает, что научной ценности данный материал не несет. Так, забавы ради.


          1. RPG18
            20.08.2019 12:29

            с другой стороны объем данного приложения должен быть весьма большим, чтобы убрать синтетичность.

            ListView на 100500 элементов уже был бы показательным. Например создает фреймворк 100500 элементов или ограничивается небольшим числом видимых элементов.


            1. dimansny Автор
              20.08.2019 12:32

              По мне так это ничуть не менее синтетично кейса из статьи. Никак не характеризует фреймворк.


              1. RPG18
                20.08.2019 12:51

                Он характеризует по потреблению памяти, а не по размеру рантайма.


                1. dimansny Автор
                  20.08.2019 12:54

                  Замечу, что характеризует по потреблению памяти конкретно в кейсе со списком. Что уже сильно ограничивает применимость результатов.


                  1. RPG18
                    20.08.2019 12:59

                    Списки и таблицы распространенные компоненты. Делаете ли UI к базе данных или клиент к социалке с бесконечной лентой.


                    1. dimansny Автор
                      20.08.2019 13:23

                      Я о другом: вы не сравниваете фреймворки, вы сравниваете реализации списков в разных фреймворках. Серьезных выводов о самом фреймворке вы не сделаете. Пример я уже привел выше — virtual scroll есть в electron (точнее в web фреймворках), и память, которую занимают элементы в DOM константна. Но что это вам говорит о фреймворке в целом?


                      1. RPG18
                        20.08.2019 13:50

                        сравниваете реализации

                        Вся статья о сравнение реализации. Вы сейчас пытаетесь увести с обсуждаемой темы.


                        1. dimansny Автор
                          20.08.2019 14:24

                          Ничуть. В конце концов кейс со списками не я предложил) Я лишь пытаюсь доказать (и об этом я уже пишу из сообщения в сообщение), что сделать несинтетические всеобъемлющие тесты фреймворков (что сравнение однооконного приложения, что сравнение списка — это сугубо синтетические тесты, не отражающие реального положения дел) — это очень сложное дело, а тем более на таком количестве инструментов. Но статья и не претендует на всеобъемлющее исследование (о чем кстати там тоже написано).


        1. Siemargl
          20.08.2019 13:25

          Наоборот, как раз базовый футпринт весьма показателен. Дальнейшее увеличение приложения приведет к росту потреблению памяти по более пологой кривой.

          Я 5 лет назад на предмет памяти смотрел расширенные примеры — грубо говоря окно, на котором отрисованы все элементы UI из библиотеки (обычно с каждой либой есть такой пример). Цифры были сравнимыми: 10-20 Мб частный рабочий набор.


          1. nikolayv81
            20.08.2019 13:43

            Конечно пологой, это как сравнить реализацию gridview от borland в delphi (где нет объекта на каждую ячейку) и от microsoft в winforms… ;)


  1. Skycaptain
    20.08.2019 11:32

    а AvaloniaUI за что пропустили?)


  1. WayMax
    20.08.2019 11:34

    Можете добавить AvaloniaUI?
    github.com/AvaloniaUI/Avalonia


    1. dimansny Автор
      20.08.2019 11:37

      Это перевод, судя по всему автор доступен в соответствующем посте на реддите. https://www.reddit.com/r/programming/comments/cr3tqx/comment/ex2f6g4


  1. RPG18
    20.08.2019 11:40
    +1

    1. нет исходного кода приложений, а значит hello world, который ничего не показывает;
    2. судя по цифрам, сюда включается разделяемые библиотеки.


  1. moya_bereza
    20.08.2019 12:17

    Прошу прощения за оффтоп. Подскажите пожалуйста инженеру-конструктору, в чем можно создавать небольшие собственные проекты с оконным интерфейсом и привязкой на с++? Что-то на подобие HiASM`a.


    1. okeld
      20.08.2019 12:46

      QT и Qt Designer, думаю, должны подойти


      1. Alexey2005
        20.08.2019 18:50

        С помощью Qt вообще реально получить exe'шник меньше 5 Мб? Да и даже для 5 Мб надо ещё сильно пошаманить со сборкой. Это просто раздутый монстр какой-то. Вот что они пихают в бинарник, что он так жиреет?


        1. Siemargl
          20.08.2019 19:07

          Вкратце — так устроен С++. Подробнее — смотреть .map от линкера.

          На скорость (в т.ч загрузки) и потребляемую память влияет мало.


          1. VioletGiraffe
            21.08.2019 16:55

            EXE-файл Win64, создающий с помощью Qt окно, весит килобайт 50, дальше уже по мере добавления кода. Это при динамической линковке с Qt и рантаймом С++.


        1. LaG1924
          21.08.2019 11:12

          Как минимум, у кьютей почти вся своя стандартная библиотека и даже больше. Как максимум, я помню, что для отключения линковки с ICU надо было очень постараться.


          1. mapron
            22.08.2019 00:49

            для отключения линковки с ICU надо было очень постараться.

            Году так в 2015?
            Сейчас никаких с этим проблем нет. Если вебкит или sqlite какой-нибудь не используешь — просто не поставляешь ICU либы, нет проблем.


        1. esaulenka
          22.08.2019 23:10

          Чтобы получить ТОЛЬКО экзешник с помощью Qt, вообще надо сильно пошаманить. Во всяком случае, я потратил довольно много времени, чтобы научиться самому собирать библиотеку статически (а всевозможные howto в мелочах устарели...). Но после этого достаточно навороченное приложение влезает в один файл на 10 мегабайт. С UPX'ом — в 4..5.



  1. TekVanDo
    20.08.2019 14:41
    -1

    Хоть и electron в глубокой попе, всё же для большинства приложений это не главное. Как по мне скорость разработки важнее если не страдает быстродействие приложения.


  1. snuk182
    20.08.2019 23:55

    Странно, что есть winapi, но нет cocoa.


  1. Cenzo
    21.08.2019 02:20

    Вот с HorusUI я ожидал примерной цифры в 20 Мб, т. к. он использует OpenGL и режим немедленной отрисовки GUI. Не понимаю, почему цифра вышла больше.

    Замапил себе в процесс какой нибудь зашаренный фреймбуфер или пару оных для теневого свопа?


  1. Beholder
    21.08.2019 15:16

    SWT отсутствует.


    Без исходников непонятно, что они там накидали в Swing и JavaFx, может там неоптимальный подход.


    1. Siemargl
      21.08.2019 16:54

      Я пробовал DWT — это прямое транскодирование SWT на D.

      Весьма компактно. Лучше, чем GtkD.

      А от Явы то чего ждать…