2014-09-27 7 views
7

Czy istnieje sposób na zwiększenie prędkości wykonywania placu zabaw? Chcę iterować wiele cykli i nie czekać 10 minut.Szybkość wykonywania zabawek Swift

Na przykład:

import UIKit 

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

Kod ten będzie wykonywał sposób zbyt długo. Ale chcę uzyskać szybki wynik.

+0

Być może optymalizujący kompilator zredukuje ten kod do: 'var count = 1000000000'. – zaph

+0

@Zaph Spróbuj wkleić ten kod na plac zabaw, a zobaczysz co mam na myśli. – zakhej

+1

Dlaczego ludzie głosują za blisko? Nie wiesz, co to jest plac zabaw? – zakhej

Odpowiedz

3

Czuję twój ból, bawiłem się z drukowaniem funkcji 2D na [Double], a następnie konwertowałem na UIImageView. Jednym z kroków była iteracja ponad milionami pikseli i trwało to wieczność.

Wszystko, co wymaga dużej mocy obliczeniowej lub jest powtarzalne lub potencjalnie czasochłonne, należy umieścić w folderze "Źródła" na placu zabaw. W ten sposób kod zostanie skompilowany przed uruchomieniem twojego placu zabaw. Umieść wyjście tej pętli for w publicznej funkcji, którą możesz wywołać z placu zabaw. Wtedy nie będziesz musiał siedzieć i patrzeć na plac zabaw, licząc, ile razy przeszedł on przez pętlę for.

0

Miałem taki problem i rozwiązałem go po kilku dniach prób. Wszystko, co musiałem zrobić, to przenieść cały mój kod do folderu Sources placu zabaw. Po tym prędkość wykonania została zwiększona. Mam nadzieję, że ci to pomoże.

Uwaga: nie zapomnij użyć klas otwartych.

2

Jednym z największych zabójców wydajności jest wynik po prawej stronie placu zabaw. Teraz pokażę ci, jak zminimalizować to wyjście.

Zobacz na końcu przykładowy kod.


Najlepszy występ

najbardziej wydajnych sposobów jest, aby cały kod krytyczny wydajności w pliku w folderze na placu zabaw Sources.swift.

Uwaga: W celu korzystania z funkcji, klas, właściwości i metod z folderu Sources trzeba je public zaznaczyć. Jeśli chcesz podklasować klasę, musisz oznaczyć ją jako open.


dobrych wyników, ale kod brzydki

Poniższy sposób (myślę, że to nie jest oficjalna/ma) może być użyty do wyłączenia wyjścia zabaw, ale także prowadzi do brzydkiego kodu. Jednak jest to dobre dla tymczasowego wyłączania wyjścia.

Istnieją dwa główne sposoby (i dwie sztuczki), aby osiągnąć minimalną ilość mocy (Jeśli okaże się lepszy sposób daj nam znać):

  1. użycie nawiasów wokół Void (lub Void?) wyrażenia, takie jak przypisania (zwykle prowadzi do braku wyników, patrz także 3.).

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

    Uwaga: W Swift zadanie powraca Void aw przypadku optional chaining jest 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. Inicjalizuj i deklaruj zmienne oddzielnie.

    var x: Int // NO output 
    (x = 0) // NO output 
    
  3. 1. Jeśli nie działa dodatkową no-op (bez operacji) wiersz powyżej lub poniżej ().

    Dzieje się zamknięć pojedynczych linii (i prawdopodobnie w innych kontekstach), na przykład: (patrz też poniższy kod)

    [1, 4, 5, 6].mmap{ 
        () // without this line the line below would yield to an output 
        ($1 = $0 + 1) 
    } as [Int] 
    
  4. Zamiast owijania każdy wiersz w nawiasie można również użyć krotka wszystkie wyrażenia, które jest następnie przypisane do zmiennej:

    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)) 
    

    jednak może to doprowadzić do katastrofy wcięcia ...

Gdzie to nie działa (Nie znalazłem sposobu, aby usunąć wyjście; Ta lista nie jest prawdopodobnie zakończyć):

  1. return s w funkcji i zamknięć
  2. Deklaracja Optional zmiennych np: var x: Int?

Przykładem nowej metody map na Sequence

Sposób użycia: Patrz wyżej w punkcie 3.

Podpis Sequence.map jest

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

Ponieważ nie znaleźli sposób, jak usunąć wyjście return s można użyć zamknięcie z inout argumentu (uzyskać „Powrót” wartość z cesją) . Ewentualny podpis może następnie być:

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

więc możemy przejść nil w inout argumentu, ponieważ jest to dobry domyślny dla każdej możliwej U bez nakładające ograniczenia na U które mogłyby wymagać generator instancji (np init() { ... }) .

Niestety, Swfit ma trudności z wnioskiem o U, więc musisz pomóc kompilatorowi z adnotacjami typu jawnego. Ponadto var newElement: U?ma powrót nil na pasku bocznym.

Teraz użyję Any zamiast 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 
    } 
} 

Twój przykładowy kod

Korzystanie 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) 
    } 
} 

Bez nawiasie: około 10,000 iteracji pętli na sekundę

Z nawiasem: około 10.000.000 powtórzeń pętli na sekundę !!!