Qual è il termine per questo tipo di refactoring


33

Sono sicuro che c'è un termine per il seguente bit di refactoring, ma non riesco a ricordarmelo e il mio Google-Fu mi sta fallendo!

Il refactor si sposta se le istruzioni nel punto in cui avranno il maggiore impatto, ad esempio cambiando questo

$test = someFunctionThatReturnsABool();
for($x = 0; $x < 10000; $x++) {
    if ($test) { 
        echo $x; 
    }
}

A questa

$test = someFunctionThatReturnsABool();
if ($test) {
    for($x = 0; $x < 10000; $x++) {
        echo $x; 
    }
}

Risposte:


56

Questo è un movimento di codice invariante in loop . Un buon compilatore dovrebbe farlo da solo.

... il codice loop invariant è costituito da istruzioni o espressioni (in un linguaggio di programmazione imperativo ) che possono essere spostate al di fuori del corpo di un loop senza influire sulla semantica del programma. Il movimento del codice invariante al loop (chiamato anche sollevamento o promozione scalare ) è un'ottimizzazione del compilatore che esegue automaticamente questo movimento ...

Se consideriamo il seguente esempio di codice, è possibile applicare facilmente due ottimizzazioni.

for (int i = 0; i < n; i++) {
    x = y + z;
    a[i] = 6 * i + x * x;
}

Il calcolo x = y + ze x * xpuò essere spostato al di fuori del ciclo poiché al suo interno sono invarianti di ciclo - non cambiano rispetto alle iterazioni del ciclo - quindi il codice ottimizzato sarà qualcosa del genere:

x = y + z;
t1 = x * x;
for (int i = 0; i < n; i++) {
    a[i] = 6 * i + t1;
}

Questo codice può essere ulteriormente ottimizzato ...


55
un buon programmatore dovrebbe farlo anche da solo, immagino
stijn il

8
Sono d'accordo @stijn - ci sono alcune cose di cui è ragionevole preoccuparsi del compilatore, ma questo non è uno di questi!
Toby,

@Toby: anche se questo è vero per il nuovo codice (dopo tutto, lo spostamento invariante del ciclo rende un ciclo interno più comprensibile), tutto ciò che è già stato fatto dal compilatore non deve essere fatto a mano. Lascerei semplicemente il vecchio codice come nell'esempio sopra; il miglioramento della qualità di LICM è piccolo e probabilmente non vale la pena.
thiton,

12
@thiton Non sono d'accordo. Lasciarlo così com'è significa che tutti i futuri manutentori dovrebbero passare attraverso lo stesso ragionamento. Spreca tempo; basta cambiarlo.
Izkata,

2
@zzzzBov sì, lo so, ma il mio punto è che quando lo schema è nascosto, probabilmente non è più esattamente lo schema. O qualcosa di simile. (scusa, lunga giornata)
stijn

10

Questo è anche chiamato hoistingo scalar promotion. Vedi qui :

Il sollevamento significa che è stata estratta un'operazione da un loop perché il loop stesso non influisce sul risultato dell'operazione. Nel tuo caso, stai sollevando il test condizionale dal ciclo while.

Riordinare significa modificare la sequenza delle istruzioni in modo da non influire sul risultato. In genere si tratta di istruzioni adiacenti senza dipendenze di dati, ad esempio non importa quale ordine si eseguano le seguenti due istruzioni:

int a = x;
int b = y;


0

Non penso che esista un tale refactoring.

Quindi, sarebbe difficile trovarlo tra gli "elenchi di refactoring".

Classificherei quell'esempio come un'ottimizzazione, non un refactoring .

Il refactoring, per me, sta cambiando il codice per migliorarne la comprensibilità senza influire sul suo comportamento.

L'ottimizzazione, per me, sta cambiando il codice per migliorare le prestazioni.

Poiché il codice ottimizzato tende ad essere meno facile da capire. Le due pratiche tendono a lavorare l'una contro l'altra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.