LINUX.ORG.RU

Поделитесь опытом тестирования многопоточных приложений

 ,


0

2

Главный вопрос: можно ли сделать порядок выполнения многопоточной программы детерминированным?

Судя по всему, ответ - нет. Тогда что можно сделать, чтобы увеличить вероятность срабатывания теста? Т.к. это, видимо, единственный путь: запускать тест 10+ раз (в зависимости от вероятности срабатывания).

Как я понял, все доступные в системе планировщики работают в kernel-space, и максимум что можно сделать - это управлять приоритетом потока. Можно, конечно, написать свой планировщик с дополнительными системными вызовами, но мне эта задача не представляется простой.

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

★★

Ответ на: комментарий от post-factum

Если да, то поделитесь, как это сделать =)

Единственное, что я придумал - писать свой планировщик. Для меня это все равно что нет.

kulti ★★
() автор топика

порядок выполнения многопоточной программы детерминированным

Еще есть yield

сжечь нА КОСТРЕ!

nanoolinux ★★★★
()
Ответ на: комментарий от post-factum

Кстати, сорри за возможное влезание в тему

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

Как это наиболее грамотным образом делать, если возможно?

westtrd
()
Ответ на: комментарий от post-factum

Да, можно придумать механизм дополнительных блокировок(может, даже лучше condition variables) для переключения потоков в нужных точках на время тестирования. Очевидно, что это что-то не очень простое(дедлоки, гонки и прочая прелесть), но явно проще самопального планировщика.

Но это все можно сделать в своем коде. А что-нибудь можно сделать для чужого? Например, STL. Или во время любой неатомарной операции.

Мне пока никаких решений в голову не приходило.

kulti ★★
() автор топика
Ответ на: комментарий от post-factum

Если мне нужна гарантия, чтобы потоку выделялось 100 проц процессорного времени ядра, если этот поток не отдает явным образом управление планировщику, куда копать? )

westtrd
()
Ответ на: комментарий от post-factum

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

func1()
{
  ...
  set_check_point(1)
  ...
}

func2()
{
  ...
  set_check_point(2)
  ...
}

test_func_1_2()
{
  set_check_point_order(1, 2, 2, 2, 1, 1, 2);
  run_in_thread(func1);
  run_in_thread(func2);
}

kulti ★★
() автор топика
Ответ на: комментарий от kulti

не хочеш проблем многопоточности ? всегда можно использовать сопрограммы никаких деадлоков и разделения данных между потоками единственное нужно будет распланировать точки переключениями между сопрограммами в винде есть нативная поддержка сопрограмм со своим стеком все как положено в бусте начиная с версии 1.50 будут сопрограммы

anonymous
()
Ответ на: комментарий от anonymous

Мне кажется, у сопрограмм немного другая ниша (хотя я про них не очень много знаю).

На сколько они будут легкими? И Можно ли в ней сделать yield, если io-wait?

kulti ★★
() автор топика
Ответ на: комментарий от westtrd

Сказать планировщику, чтобы всем процессам, кроме твоего, выдавались cpu с 7 по 12, а твоему - с 1 по 6. Потом поступить также с потоками внутри процесса.

Если я конечно правильно понял суть вопроса...

kulti ★★
() автор топика
Ответ на: комментарий от kulti

вот описание по второй ссылке с реализацией есть еще одна реализация на fiber'ах в мире виндовс она поддерживает нативное переключение стеков и там получаются настоящие сопрограммы со своим стеком так же в бусте 1.50 (сейчас 1.49) будет поддержка сопрограмм http://club.shelek.ru/viewart.php?id=338 http://www.codeproject.com/Articles/29524/Generators-in-C http://www.rsdn.ru/Forum/cpp/4662171.1.aspx

anonymous
()
Ответ на: комментарий от Int0l

С/С++ и это обсуждаться не может по независящим от меня причинам

westtrd
()
Ответ на: комментарий от kulti

Да, именно так и был задан вопрос

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

Буду признателен за некоторые подробности, по возможности с пруфами

westtrd
()
Ответ на: комментарий от Int0l

Пока только Scheme и Haskell успел попробовать. Это все интересно, конечно, но вопрос про тестирование уже существующего кода на императивном С/С++.

kulti ★★
() автор топика
Ответ на: комментарий от post-factum

Дык, можно, только они порой профит от многопоточности снижают - выполнение-то «сериализуется». Вопрос, как всегда, то ли тестирует тест. У нас, было дело, для тестирования многопоточного сервака эмулятор источника данных писали - а потом на его основе пилил тесты, не заботясь о порядке выполнения - потому что эмулятор его и так видит(«приход» куска данных эмулируется конфигом теста - явно заданными временными задержками на стороне эмулятора, входные данные и нужный выхлоп явно заданы в конфиге, клиентская часть эмулятора анализирует выхлоп сервака - совпало? Тест пройден. Конфиги позволяют довольно гибко рулить порядком исполнения с поправкой на заданное в ТЗ время реакции).

slackwarrior ★★★★★
()
Ответ на: комментарий от westtrd

А какие пруфы нужны, кроме манов?

On a multiprocessor system, setting the CPU affinity mask can be used to obtain performance benefits. For example, by dedicating one CPU to a particular process (i.e., setting the affinity mask of that process to specify a single CPU, and setting the affinity mask of all other processes to exclude that CPU), it is possible to ensure maximum execution speed for that process.

PS. Сам никогда не пробовал.

kulti ★★
() автор топика
Ответ на: комментарий от slackwarrior

Дык, можно, только они порой профит от многопоточности снижают - выполнение-то «сериализуется»

Ну эти блокировки только для тестирования же, так что не так страшно, имхо.

Можно поподробнее про ваш опыт интеграционного тестирования многопоточного сервака?

Я делаю примерно так: генерирую данные, которые отсылать и которые планирую получить в ответ. Порядка 1000 запусков - если все хорошо, значит, скорее всего, с этим куском функциональности все хорошо. Плюс запускаю двух клиентов, выполняющие конфликтующие на стороне сервера задания (как раз для отлова дедлоков и забытых мьютексов).

Вообще, хочется это все автоматизировать.

kulti ★★
() автор топика
Ответ на: комментарий от kulti

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

Вот вопрос был в том, насколько это реально работает на практике и какие подводные камни желательно учесть?

westtrd
()
Ответ на: комментарий от westtrd

можно запускать процесс на опред ядре, а другим запретить запускаться на нём, пропатчив init. На практике не использовал, описано у Р. Лава

qnikst ★★★★★
()
Ответ на: комментарий от westtrd

по русски называлась «Системное программирование» издательство O'Reilly, глава про системы реального времени.

qnikst ★★★★★
()
Ответ на: комментарий от kulti

Я делаю примерно так: генерирую данные, которые отсылать и которые планирую получить в ответ.

У нас входные данные - дампы настоящего источника данных, которые эмулятор скармливает серваку согласно своему конфигу. Сервак их парсит и вещает на клиентские группы UDP (основной канал работает по пуш-технологии, обработанные данные «пушаются» по нескольким «фидам» к подписанным на них клиентам) и по запросам клиентской части эмулятора (в зависимости от теста могут эмулироваться ошибки передачи) на адреса технологических TCP сессий, по которым гоняет рекавери-данные. Тесты - это просто секции конфига эмулятора, который сам создает клиентские подписки и рекавери-подключения, кормит сервак дампами искходных данных, эмулирует сбои связи и анализирует реакцию сервака. По сути, эмулятор - заглушка библиотеки, слушающей «боевые данные», т.е. вертится в виде нескольких потоков в составе сервака.

slackwarrior ★★★★★
()

Если это unit-тесты, то часть ситуаций можно воспроизвести вставлением mock-объектов в локами

maxcom ★★★★★
()
Ответ на: комментарий от maxcom

В общем, я что-то подобное и планирую делать. В точки пересечения потоков вставить mock-обекты, чтобы потоки синхронизировались, и таким образом увеличить вероятность сбойной ситуации. А потом анализировать, в какой последовательности они дошли до следующей контрольной точки и в каком состоянии.

kulti ★★
() автор топика

Для некоторых вещей возможна формальная верификация. Но это работает только на простых вещах (иначе займет целую вечность) и используется в основном при построении IPC-примитивов.

Комплексное тестирование - это сотни запусков на разных машинах с разными условиями (наличие/отсутствие других тяжелых процессов и их кол-во, разные процы, разные affinity mask). В принципе это автоматизируется.

Можно в код вставлять проверки (как-то: функция X должна выполняться только с одним и тем же pid и т.п.).

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

Pavval ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

Ничем, но только не тогда, когда его используют для «детерминирования порядка выполнения многопоточной программы».

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Какой вы смешной =) Точнее невнимательный читатель. Я ж написал, что скорее всего 100% задать ход выполнения нельзя, но можно косвенно повлиять на него и запускать 100500 раз.

kulti ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.