Как устранять плавающие баги
Плавающий баг это родственник пятидесятиметрового невидимого скорпиона из глубокого космоса. Этот кошмар воспроизводится так редко, что его трудно наблюдать, но достаточно часто его нельзя просто игнорировать. Вы не можете отладить баг, потому что вы не можете его найти.
Хотя после восьми часов отладки вы начнете сомневаться в этом, плавающие баги подчиняются тем же самым законам логики, что и все остальное. Что делает их трудными, это неизвестные обстоятельства, в которых они воспроизводятся. Постарайтесь записать все условия, при которых происходит плавающий баг, чтобы вы могли предположить, в чем на самом деле заключается изменчивость бага. Баг может быть связан со значениями данных, например, воспроизводиться, только когда переменной присваивается значение "Вайоминг". Если причина изменчивости не в этом, то следующим пунктом стоит проверить синхронизацию конкуррентности.
Изо всех сил постарайтесь воспроизвести баг контролируемым способом. Если воспроизвести его не получается, попробуйте поймать его через логирование. Если нужно, напишите специальные логи для этого бага, которые будут записывать то, что вам кажется связанным с ним. Смиритесь с тем, что это будет долгий процесс, если ошибка воспроизводится на боевом окружении и не по вашей прихоти. Подсказки, которые вы можете извлечь из логов, могут не дать вам полного ответа, но должны предоставить достаточно информации для улучшения самих логов. Улучшение системы логирования для боевого окружения может занять много времени. Затем вам придется ждать, пока баг не появится вновь, чтобы получить информацию из обновленных логов. Этот цикл может повториться еще несколько раз.
Самый глупый плавающий баг, который создал я, заключался в многопоточной реализации одного функционального языка программирования для учебного проекта. Я тщательно обеспечил корректную оценку параллельности программы, правильное использование ядер процессора (всех восьми в данном случае). Я просто-напросто забыл синхронизировать сборщик мусора. Программа могла работать безошибочно долгое время, завершая все задания, которые я ей назначал. Со стыдом признаюсь, я начал подозревать аппаратное обеспечение, прежде чем меня осенило, в чем проблема.
Недавно на работе у нас был плавающий баг, на который мы потратили несколько недель. У нас есть многопоточное серверное приложение на Java, размещенное на Apache-серверах. Чтобы поддержать быструю смену веб-страниц, мы выполняли все операции чтения и записи в небольшом наборе из четырех потоков, отделенных от потоков, ответственных за смену страниц. Время от времени некоторые из этих четырех потоков "замораживались" и, насколько мы могли понять из логов, прекращали делать что-либо полезное на несколько часов. Поскольку у нас было выделено четыре потока, само по себе это не было большой проблемой. До тех пор, пока не замораживались все четыре потока одновременно. Тогда очереди запросов, освобожденные замороженными потоками, забивали всю свободную память и крашили наш сервер. Нам потребовалась неделя, чтобы просто выявить баг, и за это время мы не смогли понять, в чем причина, вызывающая этот баг, и даже что именно происходило в потоках в тот момент, когда они "застревали".
Этот пример демонстрирует риск, связанный с использованием стороннего программного обеспечения. Мы использовали лицензионный код, который убирал теги HTML из текста. Хотя, к счастью, у нас был исходный код, мы не изучали его досконально, пока мы не включили логирование на нашем сервере и не увидели, что потоки почтовых сообщений забивались из-за этого лицензионного кода.
Программа работала прекрасно, за исключением некоторых длинных и необычных текстов. В этом случае время обработки текста становилось пропорциональным квадрату его длины. Если бы такие тексты встречались бы регулярно, мы бы сразу нашли баг. Если бы они вообще не попадались бы, бага просто не было бы. Как это бывает, мы потратили несколько недель, чтобы наконец понять и решить проблему.
Следующее: Как научиться проектировать программы
Last updated
Was this helpful?