Разработка для производительности

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

Конечно, для разработки для производительности, она помогает понять, какова производительность. Разделы в этой главе обеспечивают справочную информацию о факторах, влияющих на производительность, как те факторы проявляются в OS X и iOS, и как можно приблизиться к контролю тех факторов.

Что такое производительность?

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

Много людей приравнивают производительность со скоростью. Действительно, если программа выполняет сложную работу за одну секунду, Вы могли бы думать, что программа имеет хорошую производительность. Взятый отдельно, тем не менее, скорость может быть вводящим в заблуждение измерением. В сложных программных системах скорость работы не является фиксированным значением. При выполнении той же работы несколько раз при различных условиях время, которое требуется для завершения той работы, могло значительно различаться. Это вызвано тем, что программа является только одним из многих процессов, совместно использующих ресурсы в локальной системе, и использование (или злоупотребление) тех ресурсов влияет на все другие процессы.

Следующие разделы объясняют производительность с точки зрения двух различных понятий: эффективное использование ресурсов и воспринятая производительность. Оба из этих понятий оказывают важное влияние на то, как разработка и реализация Ваше приложение, и понимающий, как использовать обоих, можно привести к лучшей общей производительности.

Эффективное использование ресурсов

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

  • Процессорное время

  • Пространство памяти

  • Пространство массового хранения

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

Процессорное время

Процессорное время скупо выдано системой, таким образом, необходимо сделать самое лучшее использование того, во сколько Вы имеете. Поскольку и OS X и iOS реализуют симметричную мультипроцессорную обработку, каждый поток в системе присваивается часть времени (максимум 10 миллисекунд), в котором можно работать. В конце того времени (или прежде во многих случаях) система берет на себя назад управление CPU и дает его различному потоку.

В типичной системе со многими активными потоками, если бы каждый поток использовал свое полное выделение времени, производительность была бы ужасна. Это приводит к одной из самых важных целей по записи приложения:

Goal:If, с которым нечего делать Ваша программа, она не должна использовать процессорное время.

Лучший способ достигнуть эту цель состоит в том, чтобы использовать основанную на событии модель. Используя современные системы обработки событий, такие как те найденные в Какао и iOS, означает, что потоки Вашей программы выполняются только, когда существует работа, которая будет сделана.

Когда Ваше приложение действительно имеет работу, чтобы сделать, это должно использовать процессорное время так эффективно, как это может. Это означает выбирать алгоритмы, которые являются подходящими для объема данных, который Вы ожидаете обрабатывать. Это также означает использовать другие системные ресурсы, такие как доступный векторный модуль (AltiVec или SSE в OS X) или графический процессор, выполнять специализированные операции, который приводит к следующей цели:

Goal:Move работают из CPU каждый раз, когда Вы можете.

Для основной информации о том, как использовать процессорное время эффективно, посмотрите Фундаментальные Подсказки по Оптимизации. Для подсказок, в частности связанных с улучшением скорости операций рисования, посмотрите Код для прорисовки.

Пространство памяти

Память на современных вычислительных аппаратных средствах обычно составляется из прогрессивно медленнее (но больше) типы памяти. Самой быстрой памятью, доступной CPU, является CPU’s собственные регистры. Следующим самым быстрым является кэш L1, сопровождаемый L2 и кэшами L3, когда они доступны. Следующая самая быстрая память является оперативной памятью. Самая медленная память всех состоит из страниц виртуальной памяти в OS X, которые находятся на диске и должны быть разбиты на страницы в том, прежде чем они смогут использоваться.

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

Goal:Reduce объем потребляемой памяти Вашей программы.

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

В дополнение к сокращению объема потребляемой памяти Вашего приложения необходимо также попытаться сократить место перезаписываемых страниц памяти в приложении. Перезаписываемые страницы памяти хранят глобальную переменную или выделенные данные для Вашего приложения. В OS X такие страницы могут быть записаны в диск в случае необходимости, но выполнение так является медленным. В iOS содержание этих страниц должно быть очищено вручную самим приложением, которое могло бы позже потребовать, чтобы приложение воссоздало данные, которые были на тех страницах. В обоих случаях усилия системы высвободить память занимают время — время, которое могло быть лучше проведено, выполнив Ваш код приложения.

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

Пространство массового хранения

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

Goal:Eliminate ненужные операции файла и другие задержки до информации фактически необходим.

Удаление этого узкого места, путем устранения или задержки операций файла, важно для улучшения общей производительности приложения. Десятки миллионов циклов CPU могут передать между временем, Вы запрашиваете данные от файла и время, Ваша программа фактически видит те данные. Если Ваша программа получает доступ к большому количеству файлов, она может ожидать за многие секунды до того, как она получит все запрошенные данные.

Другая важная вещь помнить состоит в том, что Ваше приложение и любые файлы, которые оно создает, могут быть в сети вместо на локальном жестком диске. OS X, в частности делает сеть максимально невидимой, таким образом, Вы никогда не должны делать предположения о местности файлов.

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

Восприятие скорости

Даже при настройке кода приложения для оптимальной производительности для приложения полностью возможно казаться медленным пользователю. Проблема неизбежна: если у Вас есть большая работа, чтобы сделать, Вам требуются процессорное время и ресурсы для выполнения той работы. Существуют вещи, которые можно сделать, хотя дать приложению появление скорости, приводящей к следующей цели:

Goal:Make Ваша программа, быстро реагирующая пользователю.

Скорость отклика обычно является более важным фактором пользователям, чем необработанная скорость. Пока программа реагирует на команды своевременно, пользователь часто готов принять факт, что некоторые задачи занимают больше времени для выполнения. В то время как Ваша программа обрабатывает данные в фоновом режиме, восприятие скорости достигается, позволяя пользователю продолжать работать. Улучшение числа параллельных задач, выполняемых Вашим приложением, является хорошим способом сделать его быстро реагирующим пользователю. Параллелизм обычно реализуется с помощью Центральной Отгрузки или потоков. В то время как основной поток Вашего приложения реагирует на пользователя, очереди отгрузки или фоновые потоки выполняют вычисления или обрабатывают другие длительные задачи.

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

Для получения информации о том, как улучшить времена запуска, посмотрите Код Инициализации Времени Запуска. Для получения информации об улучшении воспринятой производительности Вашей программы посмотрите, Используют в своих интересах Воспринятую Производительность.

Отслеживание производительности

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

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

Установите свои базовые метрики

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

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

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

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

Измерьтесь рано, часто измеряйтесь

Данные о производительности не что-то, что можно собрать один раз и надеяться найти все узкие места производительности в программе. Проще найти проблемы при поддержании истории производительности программы. Поддержание истории упрощает видеть, улучшается ли производительность Вашего приложения или уменьшается. Если это уменьшается, можно принять меры для исправления проблемы перед поставками продукта.

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

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

Проанализируйте свои результаты

Сбор данных является самым важным шагом в идентификации узких мест производительности. Но как только у Вас есть данные, также важно, чтобы Вы использовали его для нахождения проблем. Анализ данных о производительности не так прост как рассмотрение вывода и наблюдение проблемы сразу же. Вы могли бы стать удачливыми и видеть проблему быстро, но некоторые проблемы являются более тонкими и требуют более тщательного анализа.

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

Проанализируйте высокоуровневые алгоритмы

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

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

Другие аналитические методы

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

Некоторыми дополнительными путями можно проанализировать программу, включают следующее:

  • Наблюдайте код в отладчике. Обход через код в отладчике мог бы показать логические ошибки, замедляющие код.

  • Добавьте контрольные точки к коду для журналирования информации о том, когда выполнялся тот код. Для примера использования контрольных точек для отслеживания кода инициализации см. Инструкции по Производительности Времени Запуска.

  • Попытайтесь кодировать альтернативные решения проблемы и посмотрите, сталкиваются ли они с подобными проблемами.