Когда требуется просмотр (или слой) внеэкранного рендеринга?

Привет,
В эти выходные я начал смотреть видео в WWDC 2011 года. Я нашел интересные темы о iOS. Мои фавориты были о производительности и графике, но я нашел двух из них, по-видимому, в противоречии. Конечно, я чего-то не понял. Сессиями, о которых я говорю, являются Understanding UIKit Rendering -121 и Полировка вашего приложения -105.
К сожалению, пример кода с 2011 года еще не загружается, поэтому довольно сложно иметь общий вид. В одном сеансе они объясняют, что во время визуализации в scrollview и т.д. Следует избегать внеэкранного рендеринга. Они устраняют проблемы производительности в примере кода, почти рисуя все внутри метода -drawRect. В другом сеансе проблема производительности (в представлении таблицы), по-видимому, связана с чрезмерным количеством кода в методе -drawRect ячеек таблицы.
Сначала мне непонятно, когда в системе требуется рендеринг OffScreen, я видел в видео, что некоторые функции кварца, такие как: cornerRadious, shadowOffset, shadowColor, требуют, но существует общее правило?
Во-вторых, я не знаю, хорошо ли я понял, но кажется, что при отсутствии внеэкранного рендеринга добавление слоев или представлений - путь. Надеюсь, кто-то может рассказать об этом.
Спасибо,
Andrea

Ответ 1

Я не думаю, что есть правило, записанное где угодно, но, надеюсь, это поможет:

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

Существует также очень мало практических различий между использованием слоев и представлений. Представления - это всего лишь тонкая оболочка вокруг CALayer, и они не вносят существенного снижения производительности большую часть времени. Вы можете переопределить тип слоя, используемый представлением, используя метод + layerClass, если вы хотите иметь представление, поддерживаемое CAShapeLayer или CATileLayer и т.д.

Как правило, на iOS пиксельные эффекты и графический рисунок Quartz/Core не ускоряются аппаратно, а большинство других вещей.

Следующие вещи не ускоряются аппаратными средствами, а это значит, что их нужно делать в программном обеспечении (вне экрана):

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

  • Любой слой с свойством shouldRasterize установлен в YES.

  • Любой слой с маской или тень.

  • Текст (любой вид, включая UILabels, CATextLayers, Core Text и т.д.).

  • Любой чертеж, который вы делаете самостоятельно (на экране или вне экрана), используя CGContext.

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

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

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

Для хорошей производительности, трюк заключается в том, чтобы избежать использования программного чертежа для просмотров, которые меняют каждый кадр. Например, если вам нужна анимированная векторная форма, вы получите лучшую производительность с использованием CAShapeLayer или OpenGL, чем drawRect и Core Graphics. Но если вы нарисуете фигуру один раз, а затем не нужно ее менять, это не будет иметь большого значения.

Аналогично, не помещайте тени на анимированное представление, потому что это замедлит вашу частоту кадров. Но тень на представлении, который не изменяется от кадра к кадру, не будет иметь большого негативного воздействия.

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

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

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

Ответ 2

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

Когда вы переопределяете "drawRect:", вы рисуете через CPU и выплевываете растровое изображение. Растровое изображение упаковано и отправлено в отдельный процесс, который живет в iOS, сервере рендеринга. В идеале сервер рендеринга просто отображает данные на экране.

Если вы играете со свойствами на CALayer, например, включив тени, GPU выполнит дополнительный чертеж. Эта дополнительная работа - это то, что означают инженеры UIKit, когда говорят "вне экрана". Это всегда выполняется с помощью оборудования.

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

Пока я не знаю полного списка свойств, которые вызывают проход за пределы экрана, вы можете диагностировать это с помощью переключателя Core Animation Instrument "Color Offscreen-rendered layer". Я предполагаю, что любое свойство, отличное от альфа, выполняется через внеэкранный проход.

С ранним оборудованием iOS было разумно сказать "сделать все в drawRect". В настоящее время графические процессоры лучше, а UIKit имеет такие функции, как shouldRasterize. Сегодня это балансирующий акт между временем, проведенным в drawRect, количеством выходов за пределы экрана и количеством смешивания. Для получения полной информации смотрите сеанс WWW 2014 года 419 "Расширенная графика и анимация для приложений iOS".

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

Ответ 3

Внеэкранная рендеринг/рендеринг на CPU

Самые большие узкие места для графики - внеэкранная рендеринг и смешивание - они могут возникать для каждого кадра анимации и могут вызывать прерывистую прокрутку.

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

Следующее приведет к экранированию рендеринга:

  • Любой слой с маской (layer.mask)

  • Любой слой с layer.masksToBounds/view.clipsToBounds является истинным

  • Любой уровень с layer.allowsGroupOpacity установлен на YES и layer.opacity меньше 1.0
    Когда для представления (или слоя) требуется экранированная рендеринг?

  • Любой слой с тенью (layer.shadow*).
    Советы по исправлению: https://markpospesel.wordpress.com/tag/performance/

  • Любой слой с layer.shouldRasterize является истинным

  • Любой слой с layer.cornerRadius, layer.edgeAntialiasingMask, layer.allowsEdgeAntialiasing

  • Любой слой с layer.borderWith и layer.borderColor?
    Отсутствует ссылка/доказательство

  • Текст (любой вид, включая UILabel, CATextLayer, Core Text и т.д.).

  • Большая часть рисунка, который вы делаете с CGContext в drawRect:. Даже пустая реализация будет отображаться вне экрана.


В этом сообщении описываются смешения и другие факторы, влияющие на производительность: Что вызывает внеэкранный рендеринг, смешение и layoutSubviews в iOS?