В статье расскажем как встроенные диагностические средства нашей ОС, основанные на ИИ, помогают искать и устранять проблемы в функционировании программ.




ОТПРАВНАЯ ТОЧКА


Некоторое время назад в составе нашей операционной системы появилась штатная подсистема выявления ошибок в работе ПО (amon, подробнее о ней можно почитать тут). Она вошла в состав недавно вышедшего нового релиза и основана на технологиях искусственного интеллекта.


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


Под аномалиями могут подразумеваться утечки памяти, не штатное потребление процессорного времени, не стандартная дисковая активность и т. п. Для упрощения анализа поведения утилиты top в дальнейшем она рассматривалась отдельно от авто-тестов.


После запуска amon в течении некоторого времени было выполнено обучение нейронной сети штатной утилитой amonctl на эталонной системе при запущенном top-e (для этого в течении десяти секунд имитировали штатную работу системы). После этого подсистема была переключена в режим анализа активности для того, чтобы повторить проблему, которую словили тесты.


Чтобы отследить, через какое время возникает аномальное поведение утилиты top, нам важно зафиксировать время начала анализа. Запуск сервиса amon и утилиты top произошел в 15:03. Если бы к моменту обучения amon процесс top не был запущен, его появление стало бы аномалией само по себе. Любая программа после обучения amon имеет 100% уровень доверия. Буквально за несколько секунд процент доверия снизился до 99.9, а так же появилась запись в строке «Process memory alloc anomaly», что дает понять о возможном наличии проблем с потреблением памяти.




К 15:20 процент доверия уже упал до значения в 99.6%. В дальнейшем значение девиации продолжало повышаться, но о фактических проблемах это пока не говорило, поскольку это могут быть флуктуации активности (интенсивность изменения захваченных параметров может варьироваться, в данном случае она зависела от частоты обновления состояния процессов, которая равнялась одной секунде). Решили оставить систему поработать еще пару часов.




К 17:00 процент доверия составил уже 97.1%, что уже говорило о безусловном наличии проблемы.





ВЫБОР СРЕДСТВА ОТЛАДКИ


После обнаружения проблемы перед нами встал вопрос о том, каким образом лучше будет ее локализовать и оперативно исправить. Если конкретнее — какой из отладчиков использования памяти (memory debugger) следует применить в данном случае.


Предварительно, речь шла об утечке, поскольку это наиболее вероятный сценарий. Здесь стоит упомянуть о том, что задача обнаружения проблем с памятью хоть и типовая, но нужно обладать сведениями достаточной длительности эксперимента, чтобы ее обнаружить. По этой причине утечка (возможная) оставалась незамеченной.


Вариантов анализа динамической памяти достаточно много, поэтому давайте их рассмотрим (здесь перечислены основные):


  1. Статический анализ (анализ кода без выполнения программы) хоть и не является полноценным инструментом анализа динамических аллокаций, но умеет определять отсутствие освобождений памяти в очевидных местах.

  2. Инструментирование на уровне компилятора (санитайзеры) предполагает модификацию исходного кода программы или её машинного кода для включения дополнительных проверок или логирования операций с памятью.

  3. Трассировка системных вызовов позволяет отслеживать взаимодействие программы с операционной системой через системные вызовы (например, с помощью strace или dtrace). Однако, отслеживание выделения и освобождения отдельных страниц памяти по системной трассе — процесс весьма трудоемкий.

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

  5. Динамический анализ выполнения программы — выполнение программы в управляемой среде, где каждая инструкция анализируется на лету для выявления ошибок или сбора данных (например, как это делает Valgrind через свои инструменты, такие как Memcheck или Callgrind).


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



ОТЛАДКА


Для пересборки утилиты top с отладкой включаем «dmalloc.h» во все .c файлы нашего проекта.


#ifdef DMALLOC
#include "dmalloc.h"
#endif

#include <stdlib.h>
#include <string.h>
...

И компилируем с флагом -DDMALLOC и подключенной либой dmalloc.


ntox86-gcc -DDMALLOC -DDMALLOC_FUNC_CHECK -ldmalloc top.c

Запускаем top на 1 и 30 итераций:


./top -i 1
 mv logfile top1.logfile
 ./top -i 30
 mv logfile top30.logfile

Одна итерация:


 491: top 10 allocations:
 491:  total-size  count in-use-size  count  source
 491:       52824    213       52824    213  /build/t/top/top.c:175
 491:       44160     80       44160     80  /build/t/top/top.c:151
 491:        5280      2        5280      2  /build/t/top/top.c:764
 491:         608      2         608      2  /build/t/top/top.c:200
 491:          40      1          40      1  /build/t/top/top.c:1075
 491:      102912    298      102912    298  Total of 5

Тридцать итераций:


3131: top 10 allocations:
3131:  total-size  count in-use-size  count  source
3131:       81840     31       81840     31  /build/t/top/top.c:764
3131:       52824    213       52824    213  /build/t/top/top.c:175
3131:       44160     80       44160     80  /build/t/top/top.c:151
3131:         608      2         608      2  /build/t/top/top.c:200
3131:          40      1          40      1  /build/t/top/top.c:1075
3131:      179472    327      179472    327  Total of 5

Как мы можем видеть, здесь представлен список выделений памяти в куче, в котором нас интересует сравнение колонок «total-size», которые говорят о том, что выделенная память не освобождается. Явно видно, что в строке 764 файла top.c имеет место некоторая утечка памяти, при 30-ти итерациях кол-во выделенной памяти увеличилось почти в 16 раз!


Смотрим 764 строку:


if ((ptr = (struct syspage_entry *)malloc(len)) != NULL)

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


Одна итерация:


467: top 10 allocations:
467:  total-size  count  source
467:       54808    221  /procfs-utils/t/top/top.c:175
467:       36432     66  /procfs-utils/t/top/top.c:151
467:         608      2  /procfs-utils/t/top/top.c:200
467:          40      1  /procfs-utils/t/top/top.c:1079

Тридцать итераций:


2853: top 10 allocations:
2853:  total-size  count  source
2853:       55304    223  /procfs-utils/t/top/top.c:175
2853:       37536     68  /procfs-utils/t/top/top.c:151
2853:         608      2  /procfs-utils/t/top/top.c:200
2853:          40      1  /procfs-utils/t/top/top.c:1079

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



ЗАКЛЮЧЕНИЕ


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


Подобный подход к диагностике имеет важные преимущества:

  1. Автономное обнаружение аномалий (локально на конечном устройстве).

  2. Непрерывный мониторинг работы программ.

  3. Детальная информация об изменениях в поведении системы.

  4. Журналирование аномалий для последующего изучения.

  5. Динамический многокритериальный анализ, подстраеваемый под реальный профиль функционирования конкретной системы.


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


Надеюсь, опыт окажется полезным :)



Подписывайтесь на наш канал, чтобы быть в курсе свежих новостей

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