Как отследить Heisenbug в некотором коде Python? - PullRequest
8 голосов
/ 28 сентября 2010

Краткая справка: у нас есть большая исходная база, написанная на Python. Это компилятор для предметно-ориентированного языка, а внутри все представлено в виде ориентированных графов. Эти орграфы построены из наборов, поэтому мы используем встроенный тип набора в Python.

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

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

Как бы вы диагностировали проблему, которая возникает нечасто и исчезает, когда вы начинаете ее искать?

Изменить для уточнения : Несколько ответов предлагают способы исправить порядок наборов. Как говорит torkildr ниже: «Проблема здесь не в том, что наборы ведут себя странно, а в том, что ваша программа ведет себя так, как будто она не работает». Это как раз проблема, но решение не в том, чтобы использовать детерминированные множества. Это просто замаскирует поведение. Проблема состоит в том, чтобы найти , почему наша программа ведет себя так и исправляет такое поведение. Алгоритмы, которые мы используем, должны работать с графами, представленными как неупорядоченные множества. Они не Мне нужно выяснить, где эти ошибки и почему они возникают.

Проблема решена : Оказывается, что в реализации Python, которую я использую (2.6 в OS-X), если связь между методами __eq__ и __hash__ объектов, хранящихся в наборе, не совсем корректна, то система проявляет описанное слабо случайное поведение. В реализации C. set.add () должен быть некоторый код, который использует что-то из случайного модуля для построения представления. Это вызывает зависимость от системного пула энтропии, который меняет порядок записи на диск.

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

Ответы [ 3 ]

2 голосов
/ 28 сентября 2010

Почему бы просто не изменить ничего в коде, который влияет на заданный порядок вывода, и использовать pdb вместо добавления отпечатков?Меняет ли установка точки останова также порядок расположения?Если нет, pdb позволит вам проверить внутренние переменные.

Ваше описание вашей проблемы также приведет к некоторым загадкам.Как вы обнаружите, что есть ошибка?Если это обнаружение может быть выполнено во время выполнения, возможной стратегией будет запуск pdb из вашего кода (просто import pdb; pdb.set_trace()), как только вы его увидите (используя ifs времени выполнения), а не в последующем выполнении после изменения кода,Таким образом, вам вообще не придется менять код для отладки (но, возможно, убрать эти утверждения позже, когда код будет отлажен и прочен).

Кстати, вам также следует выполнить модульное тестирование всехпри написании кода, гораздо меньше шансов скрыть скрытые ошибки.

1 голос
/ 28 сентября 2010

Раймонд Хеттингер написал рецепт для заказанных наборов .Время выполнения Big-O для всех методов такое же, как для наборов.Возможно, вы захотите изменить все свои наборы на наборы заказов.

1 голос
/ 28 сентября 2010

Я действительно не понимаю, почему вы захотите посмотреть на проблему дальше, когда у вас, очевидно, есть представление о том, в чем корень проблемы.

Основной вопрос ей таков: вам нужны детерминированные, упорядоченные графы; Наборы Python не дают вам этого. Почему бы вам не поменять реализацию на какую-то реализацию списка / набора, которая это делает?

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

edit: Подводя итог; Проблема здесь не в том, что наборы ведут себя странно, а в том, что ваша программа ведет себя так, как будто она не работает.

...