2014-09-27 5 views
7

C'è un modo per aumentare la velocità di esecuzione di un parco giochi? Voglio ripetere molti cicli e non aspettare 10 minuti.Velocità di esecuzione del parco giochi Swift

Ad esempio:

import UIKit 

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

Questo codice verrà eseguito un modo troppo a lungo. Ma voglio ottenere risultati rapidi.

+0

Forse un compilatore ottimizzante ridurrebbe quel codice a: 'var count = 1000000000'. – zaph

+0

@ Zaf Prova a incollare questo codice nel campo giochi e vedrai cosa intendo. – zakhej

+1

Perché le persone votano per chiudere? Non sai cos'è un parco giochi? – zakhej

risposta

3

Mi sento il tuo dolore, stavo giocando con la stampa di funzioni 2D a [Double] quindi la conversione in UIImageView. Uno dei passaggi era iterare su milioni di pixel, e ci voleva tempo per sempre.

Qualsiasi cosa computazionalmente intensiva, ripetitiva o potenzialmente dispendiosa in termini di tempo deve essere inserita nella cartella "Sorgenti" del parco giochi. In questo modo il codice è precompilato prima che il tuo campo giochi venga eseguito. Metti l'output di quel ciclo for in una funzione pubblica che puoi chiamare dal parco giochi. Quindi non dovrai stare seduto a guardare il parco giochi contare tutte le volte che è passato attraverso il ciclo for.

0

Ho avuto un tale problema e l'ho risolto dopo giorni di prove. Tutto quello che dovevo fare è spostare tutto il mio codice nella cartella Sources del parco giochi. Quindi, dopo che la velocità di esecuzione è stata migliorata. Spero che ti aiuti.

Nota: non dimenticare di utilizzare le classi aperte.

2

Uno dei più grandi killer delle prestazioni è l'uscita sul lato destro del parco giochi. Ora ti mostrerò come minimizzare questo output.

Vedere alla fine per il codice di esempio.


Best Performance

Il modo più performante è quello di rendere tutto il codice critica prestazioni in un file all'interno della cartella .swiftSources nel parco giochi.

Nota: Per poter utilizzare le funzioni, classi, proprietà e metodi dalla cartella Sources bisogna segnarli public. Se si desidera sottoclasse una classe deve essere contrassegnata con open.


buona prestazione ma brutto codice

Il seguente metodo (credo che questo non è ufficiale/intended) può essere utilizzato per disattivare l'uscita parco giochi, ma anche porta a codice brutto. Comunque è buono per disabilitare temporaneamente l'output.

Ci sono due modi principali (e due trucchi) per ottenere la quantità minima di uscita (Se trovate un modo migliore fateci sapere):

  1. Usa parentesi intorno Void (o Void?) espressioni come incarichi (normalmente non porta output, vedi anche 3.).

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

    Nota: In Swift un incarico ritorna Void e in caso di optional chaining è 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. Inizializza e dichiara variabili separatamente.

    var x: Int // NO output 
    (x = 0) // NO output 
    
  3. Se 1. non funziona aggiungere un (nessuna operazione) linea aggiuntiva no-op sopra o sotto ().

    Questo accade in singole chiusure di linea (e probabilmente in altri contesti), ad esempio: (si veda anche il codice qui sotto)

    [1, 4, 5, 6].mmap{ 
        () // without this line the line below would yield to an output 
        ($1 = $0 + 1) 
    } as [Int] 
    
  4. Invece di avvolgere ogni linea tra parentesi è anche possibile utilizzare una tupla di tutte le espressioni che viene poi assegnata a una variabile:

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

    Tuttavia, questo potrebbe portare a un disastro rientranza ...

Dove non funziona (Non ho trovato alcun modo su come rimuovere l'output; Questo elenco non è probabilmente completo):

  1. return s nelle funzioni e delle chiusure
  2. Dichiarazione di Optional variabili Es: var x: Int?

Un esempio di un nuovo metodo map su Sequence

Utilizzo: Vedi sopra al Punto 3.

La firma di Sequence.map è

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

Dal momento che non ho trovato un modo per rimuovere l'uscita di return s si può usare una chiusura con un argomento inout (ottenere il valore di "ritorno" con un incarico) . Una firma possibile potrebbe quindi essere:

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

così possiamo passare nil nell'argomento inout poiché è un buon valore predefinito per ogni possibile U senza imporre un vincolo U che potrebbe richiedere un generatore esempio (es: init() { ... }) .

Purtroppo Swfit ha difficoltà a dedurre U quindi è necessario aiutare il compilatore con annotazioni di tipo esplicito. Inoltre var newElement: U?fa restituisce nil nella barra laterale.

Ora userò Any invece di 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 
    } 
} 

Il tuo codice di esempio

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

Senza la parentesi: circa 10.000 iterazioni del ciclo al secondo

Con parentesi: circa 10.000.000 iterazioni di loop al secondo !!!