Тестування перегонів на багатопотокових перегонах


54

Читання коментарів до цієї відповіді , зокрема:

Тільки тому, що ви не можете написати тест, не означає, що він не порушений. Невизначена поведінка, яка, як правило, працює так, як очікувалося (C і C ++ сповнена цього), умови перегонів, потенційне переупорядкування через слабку модель пам'яті ... - CodesInChaos 7 годин тому

@CodesInChaos, якщо він не може бути відтворений, тоді код, записаний на "виправити", також не може бути перевірений. І ввімкнення неперевіреного коду є гіршим злочином на мою думку - RhysW 5 годин тому

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


1
крок через (складання) інструкція за інструкцією на обох кінцях
храповик урод

1
Статичний аналіз часто може показати потенціал UB, не ясно , якщо це вважається як тест , хоча
JK.

Вибачте, щоб запитати, але що означає "UB"?
Дуг

2
Приємне запитання, мені було б цікаво побачити потенційні рішення цього.
RhysW

1
@Doug Undefined поведінка, яка може включати, але не обмежуючись ними, умови раси
jk.

Відповіді:


85

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

Немає.

Немає хорошого загального способу викликати стан перегонів на тестуванні.

Твоє ТІЛЬКО сподівання - створити їх повністю з твоєї системи.

Коли і якщо ви виявите, що хтось інший набив собі когось, вам слід поставити йому в руки мурашник, а потім переробити дизайн для його усунення. Після того, як ви сконструювали його штучний паса (вимовляється f *** вгору) зі своєї системи, ви можете піти звільнити його від мурах. (Якщо мурахи вже вживали його в їжу, залишивши лише кістки, поставте табличку з написом "Це те, що відбувається з людьми, які вкладають умови перегонів у проект XYZ!", І ЗАЛИШУЙТЕ ТАМ.)


22
Я повністю згоден. Іншими словами, це дуже схоже на жарт - Пацієнт: "Докторе, боляче, коли я це роблю ..." Доктор: "Тоді перестань це робити!"
Марк Рушаков

Гарна відповідь. Якщо щось спричиняє неперевірену проблему, спробуйте обходити її для початку, уникайте проблеми взагалі!
RhysW

Моє єдине питання: Який великий мурашник я повинен використовувати? (+1 BTW).
Петро К.

15
+1 для правильної вимови faux pas . (І решта відповіді.)
Blrfl

1
@PeterK., Це один з небагатьох випадків розробки програмного забезпечення, поряд з моніторами, оперативною пам’яттю та дисководами, де більший IS краще.
Джон Р. Стром

16

Якщо ви перебуваєте в ланцюзі інструментів ms. Дослідження пані створили інструмент, який примусить нові переговори для кожного пробігу і зможе відтворити невдалі біги, які називаються шахами .

ось відео, яке показує це у використанні.


5
Це виглядає вражаюче; Мені доведеться знайти час, щоб спробувати це в якийсь момент.
Ден Нелі

16

Найкращий інструмент, який я знаю для подібних проблем, - це розширення Valgrind під назвою Helgrind .

В основному Valgrind імітує віртуальний процесор і запускає ваш бінарний (немодифікований) поверх нього, щоб він міг перевірити кожен доступ до пам'яті. Використовуючи цю рамку, система годин Helgrind викликає висновок, коли доступ до спільної змінної не захищений належним чином механізмом взаємного виключення. Таким чином він може виявити теоретичну умову гонки, навіть якщо вона насправді не відбулася.

Intel продає дуже подібний інструмент під назвою Intel Inspector .

Ці інструменти дають чудові результати, але ваша програма буде значно повільнішою під час аналізу.


1
чи Valgrind все ще є інструментом * nix?
Ден Нелі

1
Так, Linux, MacOSX, android та деякі BSD: valgrind.org/info/platforms.html
Жульєн

1
ThreadSanitizer - подібний інструмент. Він працює інакше, ніж Helgrind, що дає йому перевагу бути набагато швидшим, але вимагає інтеграції в ланцюжок інструментів.
Себастьян Редл

7

Викриття помилки з декількома потоками вимагає змушення різних потоків виконання виконувати їх кроки в певному переплетеному порядку. Зазвичай це важко обійтися без ручної налагодження чи маніпулювання кодом, щоб отримати якусь "ручку" для управління цим переплетенням. Але зміна коду, який поводиться непередбачувано, часто впливатиме на цю непередбачуваність, тому це важко автоматизувати.

Хороший трюк описаний Ярославом Тулачем у практичному API-дизайні : якщо у вас є заяви реєстрації у відповідному коді, маніпулюйте споживачем цих виписок журналів (наприклад, введеним псевдотерміналом), щоб він приймав окремі повідомлення журналу в конкретному коді замовлення виходячи з їх змісту. Це дозволяє контролювати переплетення кроків у різних потоках, не додаючи нічого до виробничого коду, якого там ще немає.


2
Я робив подібне перед тим, як використовувати введений сховище для сну потоків, які викликають його в певних порядках, щоб примусити перемежування, яке я хочу. Написавши код, який це робить, я схильний відповісти +1 @ Джон вище. Серйозно, цей матеріал настільки болісно правильно використовувати, і все ще дає лише найкращі гарантії здогаду, оскільки можуть бути дещо різні переплетення з різними результатами; кращий підхід - просто усунути всі можливі умови гонки за допомогою статичного аналізу та ретельного розчісування коду для будь-якого загального стану
Джиммі Хоффа

6

Неможливо бути абсолютно впевненим, що різні види невизначеної поведінки (зокрема, умови перегонів) не існують.

Однак існує ряд інструментів, які відображають велику кількість таких ситуацій. Можливо, ви зможете довести, що в даний час існує проблема з такими інструментами, навіть якщо ви не можете довести, що ваше виправлення є дійсним.

Деякі цікаві інструменти для цієї мети:

Valgrind - це перевірка пам'яті. Він знаходить витоки пам’яті, зчитує неініціалізовану пам’ять, використовує звисаючі покажчики та вихід за межі поля.

Helgrind - це перевірка безпеки потоку. Він знаходить умови перегонів.

Обидва працюють за допомогою динамічного інструментарію, тобто вони приймають вашу програму як таку і виконують її у віртуалізованому середовищі. Це робить їх не нав'язливими, але повільними.

UBSan - це не визначена перевірка поведінки. Він виявляє різні випадки C і C ++ невизначеної поведінки, такі як цілі переливи, виїзди за межі діапазону тощо.

MSan - перевірка пам'яті. Він має подібні цілі, як і Вальгрінд.

TSan - перевірка безпеки потоку. Він має подібні цілі, як Гелгринд.

Ці три вбудовані в компілятор Clang і генерують код під час компіляції. Це означає, що вам потрібно інтегрувати їх у свій процес збирання (зокрема, вам потрібно компілювати з Clang), що робить їх набагато складніше спочатку налаштувати, ніж * шліфувати, але з іншого боку, вони мають значно менші витрати на виконання.

Усі перелічені я інструменти працюють в Linux, а деякі з них - на MacOS. Я не думаю, що будь-яка робота в Windows ще надійно.


1

Здається, більшість відповідей тут помиляється на це питання як "як я автоматично визначаю умови перегонів?" коли питання справді "як я відтворюю умови перегонів при тестуванні, коли їх знаходжу?"

Спосіб зробити це - ввести синхронізацію у свій код, який використовується лише для тестування. Наприклад, якщо умова гонки виникає, коли подія X відбувається між подією A та подією B, тоді для тестування вашої програми напишіть код, який очікує, що подія X відбудеться після події A. Ймовірно, вам знадобиться якийсь спосіб ваших тестів, щоб поговорити з вашою заявкою, щоб сказати це ("ага, я тестую цю річ, тому чекайте цієї події в цьому місці").

Я використовую node.js та mongo, де деякі дії передбачають створення послідовних даних у кількох колекціях. У цих випадках мої модульні тести будуть дзвонити в програму, щоб сказати, що "налаштувати очікування події X", і як тільки програма встановить її, тест для події X запуститься, і тести згодом покажуть додаток ("я закінчую з очікуванням події X"), тому решта тестів буде працювати нормально.

Відповідь тут детально пояснює цей тип речей у контексті python: https://stackoverflow.com/questions/19602535/how-can-i-reproduce-the-race-conditions-in-this-python-code- надійно

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.