Быстрая скорость выполнения игровых площадок

Есть ли способ увеличить скорость исполнения игровой площадки? Я хочу перебрать много циклов и не ждать 10 минут.

Например:

import UIKit

var count = 0
for var i = 0; i < 1000000000; i++ {
    count++
}

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


person Artem Shmatkov    schedule 27.09.2014    source источник
comment
Возможно, оптимизирующий компилятор уменьшит этот код до: var count = 1000000000.   -  person zaph    schedule 27.09.2014
comment
@Zaph Попробуйте вставить этот код на игровую площадку, и вы поймете, что я имею в виду.   -  person Artem Shmatkov    schedule 27.09.2014
comment
Безумное закрытое голосование на этом сайте действительно становится проблемой. Отличный вопрос и спасибо, что разместили его.   -  person Fattie    schedule 27.09.2014
comment
@Zaph - вы наверняка понимаете, что это типичный пример тестового кода ??? Зах - еще раз спасибо за поднятие этого   -  person Fattie    schedule 27.09.2014
comment
Я бы посоветовал вам просто не делать таких вещей на детской площадке. Я чувствую, что Apple намерена использовать игровые площадки для тестирования небольших фрагментов и идей, а не для запуска чего-нибудь миллиард раз. Поскольку весь код повторно выполняется, когда вы его редактируете, и имеет отображение значений в реальном времени и т. тривиально. Как отмечали другие, оптимизирующий компилятор просто убьет ваш цикл, а многие другие функции оптимизаторов сделают невозможным просмотр игровой площадки в реальном времени.   -  person Matt Gibson    schedule 27.09.2014
comment
Конечно, это пример кода, который не имеет отношения к реальным приложениям, и игровая площадка не является готовой конфигурацией. Что поставляется с оптимизацией выпуска, попробуйте это. @ Джо, я согласен с закрытым голосованием.   -  person zaph    schedule 28.09.2014
comment
На новых игровых площадках есть папка Sources, куда вы можете поместить свои файлы Swift, которые будут выполнены один раз и станут доступны из Playground. Это ускорит игровые площадки   -  person Kostiantyn Koval    schedule 17.05.2015
comment
Я использовал Playgrounds не для измерения производительности, а для некоторых вычислений. Вопрос актуальный.   -  person Kartick Vaddadi    schedule 07.08.2017


Ответы (4)


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

Смотрите в конце ваш пример кода.


Лучшее представление

Самый эффективный способ - сделать весь критический для производительности код в .swift файле внутри папки Sources на игровой площадке.

Примечание. Чтобы использовать функции, классы, свойства и методы из папки Sources, вы должны отметить их public. Если вы хотите создать подкласс класса, он должен быть помечен как open.


Хорошая производительность, но уродливый код

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

Есть два основных способа (и два приема) для достижения минимального объема вывода (Если вы найдете способ лучше, дайте нам знать):

  1. Используйте круглые скобки вокруг Void (или Void?) выражений, таких как присваивания (обычно не приводит к выводу, см. Также 3.).

    var x = 0       // output: 0
    (x = 1)         // NO output
    (x = 2 * x - 1) // NO output
    (x.negate())    // NO output
    

    Примечание. В Swift назначение возвращает Void, а в случае необязательное связывание это Void?.

    var x: (Int, Int)? = nil
    if (x?.0 = 0) != nil {
        // assignment was successful (x!=0 and now x=(0, x.1))
    } else {
        // assignment was not successful (x==nil)
    }
    
  2. Инициализировать и объявлять переменные отдельно.

    var x: Int // NO output
    (x = 0)    // NO output
    
  3. Если 1. не работает, добавьте дополнительную строку no-op (no operation) выше или ниже ().

    Это происходит при закрытии одной строки (и, возможно, в некоторых других контекстах), например: (см. Также код ниже)

    [1, 4, 5, 6].mmap{
        () // without this line the line below would yield to an output
        ($1 = $0 + 1)
    } as [Int]
    
  4. Вместо того, чтобы заключать каждую строку в круглые скобки, вы также можете использовать кортеж всех выражений, который затем присваивается переменной:

    var a: Any // this may be a useful definition in this context
    var x: Int
    var y: Int
    (a = (x = 0,
          y = 1,
          x = y + 1,
          y = x*x))
    

    Однако это могло привести к катастрофе с вдавливанием ...

Где это не работает (я не нашел способа удалить вывод; этот список, вероятно, не полный):

  1. returns в функциях и замыканиях
  2. Объявление Optional переменных, например: var x: Int?

Пример нового map метода на Sequence

Использование: см. Выше в пункте 3.

Подпись Sequence.map

func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]

Поскольку я не нашел способа удалить вывод returns, можно использовать закрытие с аргументом inout (получить "возвращаемое" значение с присваиванием). Возможная подпись тогда могла бы быть:

func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]

поэтому мы можем передать nil в аргументе inout, поскольку это хорошее значение по умолчанию для всех возможных U, без наложения ограничений на U, для чего может потребоваться генератор экземпляров (например: init() { ... }).

К сожалению, Swfit с трудом выводит U, поэтому вам нужно будет помочь компилятору с явными аннотациями типов. Кроме того, var newElement: U? возвращает nil на боковой панели.

Теперь я буду использовать Any вместо U?:

extension Sequence {
    // ATTENTION: this is not as performant as the normal `map`!
    func mmap<U>(transform: (Element, inout Any) -> ()) -> [U] {
        var result: [U]
        (result = [U]())
        for element in self {
            var newElement: Any
            (newElement = 0) // some placeholder element
            (transform(element, &newElement))
            // assume the inout element to be of type `U`
            (result.append(newElement as! U))
        }
        return result // the ONLY output in this method
    }
}

Ваш пример кода

Использование Swift 4

var count = 0
for i in 0..<1_000_000_000 {
    (count += 1)
    if count % 100_000 == 0 {
        // print only every 100_000th loop iteration
        print(count)
    }
}

Без скобок: около 10.000 итераций цикла в секунду.

В скобках: около 10.000.000 итераций цикла в секунду !!!

person Qbyte    schedule 28.11.2017

Я чувствую вашу боль, я играл с печатью 2D-функций в [Double], а затем конвертировал в UIImageView. Одним из шагов было перебор миллионов пикселей, и это заняло целую вечность.

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

person dsgrnt    schedule 30.01.2016

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

Примечание: не забывайте использовать открытые классы.

person Kirill Averyanov    schedule 15.03.2017

Чтобы ускорить сборку в Xcode Playground и предотвратить бесконечное вращение значка загрузки:

  1. перейдите на боковую панель справа и измените iOS на macOS в настройках Playground
  2. вместо импорта UIKit импортируйте Foundation (это будет работать, если вы не пытаетесь использовать определенные вещи из инфраструктуры UIKit)
person Kelvin Jou    schedule 09.04.2021