Отладка многопоточных приложений
Получив в очередной раз трудновоспроизводимый баг в жутко многопоточном окружении, начинаешь задумываться - а как бы упростить себе жизнь? Как бы сделать так, чтобы такие баги было гораздо проще поймать?
Ведь обычно такие баги прячутся очень хорошо - они могут проявляться раз в год на нормальной машине, но на определенных компьютерах вдруг они начинают вылезать каждые 5 минут. Например, так часто бывает на медленных компьютерах - на них баги с многопоточностью вылезают особенно часто.
И сегодня мне в голову пришла интересная идея. А что если бы в ядре ОС у планировщика потоков была возможность “эмуляции” стресс тестирования для потоков? Это бы очень сильно упростило жизнь разработчикам.
Я имею в виду, например, чтобы планировщик давал потокам минимальные окна для работы, плюс чтобы эти окна были случайные.
Ведь в чем проблема с медленными компьютерами? В том, что на быстрых определенный код успевает обычно отработать до переключения потоков, а на медленных - не успевает. Потом в другом потоке что-то удаляется или блокируется и, когда управление возвращается обратно - происходит баг. Это один из основных сценариев.
И если бы планировщик потоков мог бы рандомизировать переключения потоков, то программисты бы могли все такие ситуации тестировать на своих машинах, а не на машинах пользователей.
Вообще, можно придумать много сценариев работы для планировщика, которые могли бы помочь в тестировании и отладке и проблема только одна - даже если я придумаю их сто штук, я не смогу их реализовать.
И вот тут все любители Linux должны воскликнуть “Ага!”. И точно - “ага”!
В Linux любой может залезть в ядро и поменять алгоритм работы планировщика потоков. Так что можно будет собрать специальное ядро для тестов и тестировать на нём.
У разработчиков для Windows и MacOS такой возможности нет и остается только ждать милости “гигантов”…
Понравилась статья? Подпишись на RSS!
Для Java есть http://javapathfinder.sourceforge.net/
Для Java много чего есть - там же виртуальная машина, а значит полный контроль за исполнением. Хорошо, что не поленились это туда добавить.
А под .Net такое сделать нельзя?
И ещё можешь почитать http://antilamer.livejournal.com/279512.html для общего интереса и развития
Ага, видел
И вот ещё из каментов http://savenkov.lvk.cs.msu.su/mc.html
Ты же понимаешь - не всё можно проверить схемой и не для всего в реальной жизни можно эту схему построить.
Почему у разработчиков Windows нет такой возможности? Никто не мешает написать свой драйвер шедулера. Под Windows CE это точно возможно. Под Win Vista нужно подробнее смотреть - возможно есть какая-то защита от левых драйверов.
Хм, разве? А где про это можно почитать для Vista\W7\XP?
Насчет Vista видимо я что-то напутал. Русинович пишет, что шедулер там в микроядре.
А про Windows CE можно почитать в DDK по этой ОС. Но там ядро в сорсах, поэтому править несложно.
Конечно иметь возможность воспроизвести баг - это уже хорошо… то есть типа потенциальная возможность воспроизведения. Можно всякой отладки, бряков напихать и ждать…
Но было бы гораздо лучше - если воспроизводимость ошибки приближалась к 100%… Чтобы не сидеть и не ждать пока повезет.
Вообще нельзя в таком ответственном деле уповать на случай.
Поэтому генератор случайных чисел - фтопку. Лучше фиксированные значения.
Можно и фиксированные. Если бы была возможность менять шедулер - можно было бы сделать какой угодно алгоритм.
helgrind из состава valgrind часто помогает найти такие баги…
Microsoft Application Verifier это случайно не то, что нужно?
Описание
Среди тестов есть такие:
Low resource simulation tries to simulate an environment under low resources, whereby you can define a number (0–100) that indicates the fault probability calls of:
* Wait (for example. the WaitForXXXX API).
* Heap_Alloc (Heap Allocation API).
* Virtual_Alloc (Virtual Memory allocation API).
* Registry (Registry API).
* File (File API such as CreateFile).
* Event (Event API such as CreateEvent).
* MapView ( MapView API such as CreateMapView).
* Ole_Alloc (Ole API such as SysAllocString).
Я вот тоже хотел про сию тулзу заметить.
Это не совсем то - они вроде как просто тормоза системы эмулируют. Хотя да, Application Verifier - мега тулза. Сейчас играюсь как раз с ней
Потоки нужно тестировать на медленных машинах с небольшой памятью. Если поток не освобождает память, она быстро кончится.
Гиганты смилостивились и сделали Chess: http://research.microsoft.com/en-us/projects/chess/
Chess: http://research.microsoft.com/en-us/projects/chess/
майкрософт сделали сhess, можно найти на technet
Смысл тулзы как раз в том, чтобы по-разному шедулить потоки, создавая всевозможный интерливинг.
Ну и предполагается, что под ней будут работать “юнит”-тесты.
Chess - другое. Это типа юнит тестинга для потоков. С ним надо строить приложение и писать спец. тесты.
Ядро в OS X вполне себе opensourced
А еще можно писать так, чтобы баги, связанные с нарушением синхронизации не появлялись вообще
(барабанная дробь, входит Haskell. В руках у него книжка Hoare, в рюкзаке - STM (software transcational memory))
А еще можно писать так, чтобы баги вообще не появлялись. Не только связанные с синхронизацией, а вообще… Кто-то в это верит?
можно по крайней мере радикально сократить их количество, если писать не на ассемблере-переростке
Это факт, да. Писать на С или “С с классами” в 21 веке - нонсенс. Однако же до сих пор самые критические приложения на них пишутся…
по моему опыту - это в основном инертность мышления, а ни какая-то необходимость… а опыт у меня достаточно наглядный
>> по моему опыту - это в основном инертность мышления, а ни какая-то необходимость…
Не всегда. Если С используется для создания простых коммерческих тулзов или гуишных приложений - безусловно.
Но есть еще сферы, где C почти стандарт, а не Java или .Net, не говоря уже о Lisp. И там это пока не меняется - это высокопроизводительные вычисления. Типа игр или антивирусов. Или драйвера.
я сам пишу софт для безопасности, и вижу, что во многих местах С++ излишне усложняет разработку. Критические (в части скорости) части можно написать на C/C++, а основную логику - на чем-то другом, более безопасном
Это если можно выделить такие “некритические части”.
Так что это ловушка.
Например, у нас на С++ не пишутся всякие тесты, простые тулзы и т.п. - для этого python или другой скриптовый язык отлично подходит.
Но когда дело доходит до чего-то, что должно работать у кастомера в составе продукта - тут уже сразу строго только C++. Даже гуи на C++.
Хотя я бы может часть продукта и написал на другом языке - ГУИ, тулзы, вспомогательные компоненты. Но опять же проблема - если в компании пишут на С, то ВСЕ пишут на С. А значит на Java или .Net даже тулзов не написать - их тупо почти никто не знает
да и насчет игрушек - я, насколько помню, кто-то из популярных леталок был написан на Яве
Да, в IL-2 штурмовике было что-то на яве написано. Какая-то часть. А в рейнджерах на Delphi логику писали. Каждый пишет на том, что ему ближе, но всё равно 95-99% в геймдеве до сих пор - С++.
Хотя должен сказать, что там тулзы и другие вспомогательные программы гораздо чаще на других языках пишут. В геймдеве изменяться больше готовы, чем в других отраслях. Гибче он
Это что то может быть например загрузчиком скриптов или еще чего то что делается один раз в игре при загрузке и где производительность не имеет значения…
Не понял, у вас коментарии премодерируются или какой-то двудневный лаг между отправкой и их появлением? пытался несколько раз отправить в первый день, и только 4я чтоли попытка удалась. А теперь вижу их все идущими подряд
Это антиспам фильтр так работает - он подозрительные сообщения отправляет мне на модерацию. Обычно те, где есть ссылки, считает подозрительными. А я не так часто в список подозрительных захожу, чтобы отфильтровать - уж больно много спама приходит.
Но такой фильтр лучше, чем его отсутствие - иначе бы по 5-10 спам-комментов в день приходило.
А еще есть Intel Parallel studio, судя по презентации на techdays.ru это именно то, что доктор прописал.
У Intel и до этого были тулзы для этих и др. целей… типа Intel VTune только для потоков как то по другому называется…
А вообще, нормальный код и при многопоточности работает без проблем!
Отладьте все что крутится в потоке, проверьте логику синхронизации и проблем не дожно быть.
Для тестирования на “коленке” (имитация медленной машины) в голову приходит задать низкие приоритеты рабочим потокам и запустить поток с высоким приоритетом и циклом который будет бегать ничего не делая и грузить процессор.
По поводу имитации схемы работы или повторения не воспроизводимого стабильно бага, скажу у самого несколько таких проектов, в которых огромное количество путей в зависимости от постоянно идущих входящих данных/параметров и выбор ветки и обработки в зависимости от них и постоянно меняющихся внутренних данных. Ну и конечно все работает паралельно с большим, произвольным количеством потоков. Баг всегда удавалось выловить путем анализа и протоколирования хотя бы части данных, хоть раз да попадет набор данных с которым баг проявляется. Хотя повторюсь в 95% случаев найденная бага никакого отношения к многопоточности не имеет а скорее из-за модели которая с ростом стала слишком сложной для понимания и контроля… т.е. рефакторинг убрал бы сразу 80-90% ошибок. Но проект старый, все всё позабывали и трогать не хотят.
Было бы все так просто
Я сейчас склоняюсь в сторону стресс тестов для тестирования многопоточности. Пишу специльные тесты, в которых гоняю в максимально напряженном режиме код с кучей потоков и на каждой строчке кода вставляю рандомный Sleep. В итоге все возможные варианты переключения потоков за день-два происходят и все баги находятся и фиксятся.
Потом этот стресс тест добавляется в тест аутомейшен и вуаля - защита от будущих багов