Задача

Со временем Skype выявил, что один из элементов их системы, распознаватель телефонного номера (PNR) работает плохо. Это вызывает определенные сложности у клиентов, которые в дальнейшем перерастают в жалобы и в конечном счете приводить к неудовлетворенности всем брендом Skype. Проблема заключается в том, что в коде PNR есть узкие места и ошибки, это приводит к тому, что приложение плохо работает или вообще зависает. Skype обратился к Softage с просьбой внимательно ознакомиться с кодом и подготовить подробный отчет о найденных недостатках. Наша команда разработчиков изучила код в мельчайших подробностях и выявила многие недостатки, которые требуют внимания. Руководство Skype оказалось настолько довольно предоставленным нами докладом, что предложило нам подключить наших специалистов к их команде и работать, чтобы исправить недоработки, которые мы выявили.

Обзор решения

Наша команда быстро идентифицировала проблему, разработала и реализовала решения, развернув значительно улучшенный PNR. Результаты нашей работы поразили команду Skype. Пересмотренный PNR в двенадцать раз эффективнее предыдущей версии. Он находит больше телефонных номеров, делает это быстрее и качественнее. Кроме того, наши специалисты значительно сократили количество кода в процессе. Мы также настроили внутренние инструменты, чтобы приложение стало кросс-платформой, и теперь одинаково хорошо работает в Windows, Mac OS X или Linux.

Основные функции

Инженеры Skype поставили три основные задачи. Прежде всего, они хотят, чтобы мы перенастроили код, чтобы улучшить стабильность и производительность приложения. Во-вторых, они хотят, чтобы PNR не только распознавал больше телефонных номеров, но и лучше анализировал найденные им числа и приписывал им правильные характеристики. Например, является ли номер мобильным или стационарным, является ли он номером факса и имеет ли он правильный код страны, приписываемый ему. Наконец, они хотят, чтобы PNR был кодом, стабильно работающим на Mac для OS X и Linux. Все это должно быть достигнуто без какого-либо значительного увеличения объема кода и готового продукта, который найдет по крайней мере столько же телефонных номеров, что и предыдущая нестабильная версия.

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

В аналогичном ключе мы обнаружили, что результаты расчетов не сохраняются, поэтому, когда этот расчет снова понадобится, это потребует повторного многократного расчета. Там, где это возможно, наша команда пересматривает код для хранения результатов вычисления как временной переменной или частного члена класса, а затем ссылается на это значение, а не повторяет вычисление. Мы также постарались оптимизировать алгоритмы, чтобы обеспечить, по возможности, бинарный, а не линейный поиск, что значительно сокращает время, необходимое для полного поиска.

Стабильность была главной проблемой с предыдущей версией PNR и осталась ключевой областью внимания. Наша команда Softage идентифицировала ряд причин, способствующих этому. Для начала, обработка исключений была очень плохо настроена. Имеющиеся внутри системы исключения выбрасывались, что в итоге вызывало сбой работы инструмента. Мы заключили все внешние функциональные интерфейсы между PNR и внешним кодом в блоки try-catch, что обеспечило значительное улучшение стабильности. Это улучшение еще больше усилилось благодаря внедрению синхронизации потоков для предотвращения одновременного изменения объектов в нескольких потоках.

Вторая область сложности, которую идентифицирует наша команда, – это использование динамической памяти. Это очень плохо контролируется в исходном PNR и вызывает значительные утечки памяти. Там, где это возможно, наша команда полностью отключает использование динамической памяти, а там, где это невозможно, мы внедрили для нее значительно улучшенные средства управления.

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

Хотя есть множество других незначительных проблем, которые мы решили в ходе проекта, есть один последний существенный недостаток, который при исправлении дал значительное улучшение надежности: мы заметили, что часть процессов выполняются в одной части PNR, а затем переходят в другие части, тем самым замедляя работу всего приложения. Мы внедрили концепцию черного ящика (супер секрет, мы об этом не расскажем), которая запрещает рутине в одной части приложения видеть операции в другой, оставляя их в пределах своих собственных задач.

Инструменты и технологии

Microsoft Visual Studio 2005, Xcode 3 series, Boost C ++ Library и Active Template Library