Одна и та же операция занимает разное время выполнения в двух одинаковых проектах - PullRequest
3 голосов
/ 04 апреля 2020

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

Я наблюдал за использованием ЦП, и похоже, что новое приложение использует меньше ЦП и получает очень мало потоков, в то время как старое получает много потоков для той же задачи. PS: я использую то же устройство.

Что может вызвать это? Любые идеи или предложения, чтобы узнать?
Спасибо.

Ответы [ 2 ]

3 голосов
/ 09 апреля 2020

Наконец-то я нашел проблему. Это было вызвано установкой Optimization Level в Xcode Build Settings. Когда создается новый проект, по умолчанию Debug уровень оптимизации равен none, а Release уровень оптимизации равен Fastest, Smallest [-Os] Поэтому, когда я изменил Debug на Fastest, Smallest [-Os], время выполнения моей задачи упало до 1 se c.

От Apple:

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

Если вы хотите чтобы узнать больше об уровнях оптимизации и производительности: Настройка производительности и отзывчивости

Примечание: изменение уровня оптимизации на самый быстрый, Наименьшее [-0s] в режиме отладки может повлиять на точки останова отладчика и это будет вести себя внезапно.

Приветствия.

1 голос
/ 11 апреля 2020

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

Я хотел бы подчеркнуть, как вы НЕ должны делать длительные пробежки операция на основном потоке. Без причины. На самом деле, если вы хотите, чтобы экран обновлялся sh 60 раз в секунду (что всегда должно быть вашей целью), это означает, что каждый блок кода, который вы отправляете в основной поток, должен длиться менее 0,016 секунды (1/60), чтобы избежать потерять несколько кадров. Если, тем временем, вам также нужно, чтобы основной поток выполнял какую-то сложную анимацию и другие вещи, вполне вероятно, что вам нужно go далеко за 0,016 секунды.

Если вы заблокируете основной поток для гораздо больше (например, 1 секунда в этом случае), чем пользователи будут испытывать застрявший интерфейс, они не могут прокручивать scrollView или перемещаться по приложению. Они также могут полностью закрыть ваше приложение, поскольку они могут чувствовать, что оно застряло.

В вашем случае, например, вы можете захотеть добавить хорошую анимацию загрузки, такую ​​как ActivityIndicator или более приятную анимацию, к express, на самом деле вы работаете в этот момент и не зависли. Это действительно ожидается пользователями в настоящее время. Вы можете (или нет, это зависит от вас) также захотеть добавить кнопку отмены, если пользователь хочет отменить длительную операцию и сделать что-то еще с вашим приложением.

Чтобы избежать слов, вызывающих потерю производительности (задача замедляется до 7-8 секунд), вы можете использовать serialQueue с высоким качеством обслуживания . Возможно, userInitiated - это то, что вам нужно.

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

Если это все еще слишком низкая производительность, вы можете подумать о разделении задачи на подзадачи и выполнении их параллельно, используя DispatchQueue.concurrentPerform (iterations: execute:) (но я не знаю, выполнимо ли это в вашем случае).

Надеюсь, это вам поможет. Приветствия

...