В предыдущей статье Жирные программы-факторы скорости были набросаны наметки по теме — почему программы "тормозят".


Был выделен фактор памяти, как важный, но не было идей по его тестированию его “жирности” в зависимости от фреймворка. И вот, приняв на праздниках спокойное правильное состояние, я такую идею сгенерировал.


Была написана утилита, которая позволяет измерить время загрузки программы и связанные с этим расходы — дисковый ввод/вывод и потребляемую память. Ссылка в конце статьи.


Некоторые тесты под катом.



Возьмем три похожие программы — мини-IDE, написанные соответственно на разных языках и использующие разные фреймворки — в таблице


Программа Язык Фреймворк Ссылка
DrJava Java8 Swing+JGoodies http://www.drjava.org
Notepad++ C++ WinAPI+Scintilla https://notepad-plus-plus.org
SharpDevelop C# .NET 4.5 http://www.icsharpcode.net/OpenSource/SD/Default.aspx

Каждая программа тестируется после загрузки виртуальной системы — замеряем время первого и повторного запусков. Конфигурация виртуальной машины — чистая Windows 7, 1Gb памяти (340Мб используется под нужды ОС), 2 ядра. Хост — i5 3.2GHz, 8Gb памяти.


Тест 1 — время до открытия окна и запуска очереди сообщений


Смотрим Starting Time. После запуска утилита stime каждые 3 секунды выводит статистику по памяти и дисковому вводу выводу (ошибки страниц), что позволяет мониторить динамическую подгрузку модулей фреймворка.


stime.exe "C:\Program Files\Notepad++\notepad++.exe"
DiskIO: 15.922MB WorkingSetSize: 13.613MB PagefileUsage: 7.5117MB
Starting time is 1333.03 ms, Повторный запуск: 196.751 ms

stime javaw -jar D:\Downloads\drjava-beta-20160913-225446.jar
DiskIO: 96.953MB WorkingSetSize: 72.559MB PagefileUsage: 82.148MB
DiskIO: 103.76MB WorkingSetSize: 73.621MB PagefileUsage: 91.965MB
Starting time is 5963.89 ms, Повторный запуск: 4541.6 ms

stime.exe -splash "C:\Program Files\SharpDevelop\5.1\bin\SharpDevelop.exe"
DiskIO: 85.934MB WorkingSetSize: 54.414MB PagefileUsage: 45.117MB
DiskIO: 136.74MB WorkingSetSize: 71.609MB PagefileUsage: 66.969MB
DiskIO: 137.43MB WorkingSetSize: 72.09MB PagefileUsage: 67.035MB
Starting time is 7863.89 ms, Повторный запуск: 1405.49 ms

Была замечена небольшая некорректность со временем старта — время засекается функцией, контролирующей начало обработки очереди сообщений — но некоторые программы, например DrJava, начинают ее обрабатывать в фоновом режиме, хотя загрузка еще продолжается очень долго.


Потому для Явы используется обходной путь — ожидаем дополнительно появления видимого окна с непустым заголовком.


Аналогично, для SharpDevelop ожидание создания главного окна и подавление сплеш включено специальной опцией. И даже после появления главного окна SharpDevelop еще прилично подгружался — что видно по DiskIO через 3с после старта.


Еще интересный момент — когда виртуальная машина была сконфигурирована однопроцессорной — время загрузки Явы вырастало втрое (~35c), для С++ и .NET программ это не влияло.


Тест 2 — время загрузки файла исходного кода и отработки команды выхода


При запуске с опцией -quit, утилита stime сразу после запуска дочернего процесса посылает команду закрытия WM_QUIT. Смотрим Full run time — засечку по выгрузке процесса из памяти.


stime.exe -quit "C:\Program Files\Notepad++\notepad++.exe" stime.cpp
DiskIO: 16.734MB WorkingSetSize: 14.32MB PagefileUsage: 8.0664MB
Full run time is 1611.67 ms, Повторный запуск: 240.524 ms

stime.exe -quit javaw -jar drjava-beta-20160913-225446.jar JsonIterator.java
DiskIO: 97.992MB WorkingSetSize: 75.52MB PagefileUsage: 100.41MB
Full run time is 6860.405 ms, Повторный запуск: 4533.613 ms

stime.exe -splash -quit "C:\Program Files\SharpDevelop\5.1\bin\SharpDevelop.exe" kernel.cs
DiskIO: 127.4MB WorkingSetSize: 68.148MB PagefileUsage: 53.133MB
Full run time is 9752.181 ms, Повторный запуск: 3066.784 ms

Здесь тоже приходится применять обходной путь для Явы — после того, как окно приложения закрылось, пристреливаем javaw.exe


> Исходники программы stime и бинарник на GitHub


Выводы — загрузка фреймворка — очень дорогая операция, поскольку стоит большого количества рандомного ввода-вывода. Хотите быструю программу — делайте ее компактными средствами.


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

Поделиться с друзьями
-->

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


  1. remzalp
    10.05.2017 20:37

    Bernard Goossens уже несколько лет пилит идею профайлера, который будет выдавать всегда повторимые результаты времени выполнения при одинаковых входных данных и любом количестве перезапусков. Идея в том, чтобы запускать программу на эмуляторе процессора, который аккуратно будет отчитываться в логи. В этом случае убирается воздействие кода операционной системы, который выполняется параллельно.
    Пока что только ARM архитектура поддерживается.


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


    1. lany
      10.05.2017 20:48

      Ну можно как минимум hardware performance counters заиспользовать, они стабильнее. Количество выполненных инструкций, например, считать. Хотя суперстабильности всё равно не будет. JIT-компилятор в Java, например, легко выдаст неустойчивый результат в зависимости от гонки между потоками. То есть гонка на ранней стадии работы программы повлияет на сгенерированный ассемблерный код, который будет с вами до конца работы программы и может дать вполне ощутимую разницу в производительности.


      А тут ещё в IO многое упирается. На рамдиске наверняка будут существенно другие результаты. Поэтому замеры чисто процессорного времени непрактичны.


  1. lany
    10.05.2017 20:43

    О, DrJava. Забавная поделка, никогда не слышал о ней.


  1. a1888877
    10.05.2017 21:48
    +4

    Т.е. вы взяли три разных программы, по одной от Java/C++/C# и по скорости их загрузки делаете выводы о среде выполнения? Вам не кажеться, что между «экспериментом» и выводом причинно следственных связей нет? Без относительно того, сколько environment java/.net отжирает?


    1. Siemargl
      10.05.2017 21:52
      +1

      Мне кажется, что связь все-таки есть.

      Чтобы запустить свою небольшую программу — приходится загрузить с диска 100Мб => (следовательно) загрузка медленная.

      Инструмент приложен — можно пробовать подтвердить или опровергнуть гипотезу. На своих примерах.


  1. cranium256
    11.05.2017 02:46

    Проблема в том, что сейчас редко кто уделяет внимание эффективности программ. Об этом просто не заморачиваются.


  1. ssh24
    11.05.2017 09:12

    Любопытно, почему в своем тесте вы выбрали DrJava, а например не jEdit?
    С другой стороны, чтобы посильнее задвинуть джаву, то надо было брать сразу Eclipse.


    1. Siemargl
      11.05.2017 10:09
      -1

      Например, потому что не знал про него. Симпатичная программка.

      jEdit, Java8, Swing

      Тест 1

      DiskIO: 58.906MB WorkingSetSize: 50.844MB PagefileUsage: 59.063MB
      DiskIO: 61.371MB WorkingSetSize: 52.121MB PagefileUsage: 79.465MB
      Starting time is 5577.73 ms Повторный запуск: 2917.75 ms

      Тест 2
      DiskIO: 58.496MB WorkingSetSize: 51.059MB PagefileUsage: 59.078MB
      Full run time is 5420.59 ms Повторный запуск: 2581.902 ms

      Компактнее и быстрее, чем DrJava


    1. aleksandy
      18.05.2017 12:46

      Не Eclipse, а Netbeans или Idea.

      Eclipse на swt писан, который весь UI делегирует нативным библиотекам. А вот Netbeans/Idea — это свинговые приложения.