2011-11-25 12 views
5


Ho trovato questo in qualche codice che volevo ottimizzare. Ecco lo snipet:È un normale comportamento regex di Java?

tempString = bigBuffer.replaceAll("\\n", ""); 
tempString = tempString.replaceAll("\\t", ""); 

Poi ho deciso di usare l'espressione regolare con saggezza e ho fatto questo:

tempString = bigBuffer.replaceAll("[\\n\\t]", ""); 

Poi un amico mi ha detto di fare questo, invece:

tempString = bigBuffer.replaceAll("\\n|\\t", ""); 

Dato che mi piace conoscere il risultato delle mie modifiche, ho fatto un test per verificare se fosse una buona ottimizzazione. Quindi, il risultato con (versione java "1.6.0_27") è con il primo codice che è il riferimento al 100%.

Con il tubo è il 121%, quindi è necessario più tempo per eseguire l'operazione.

Con la parentesi quadra è del 52%, quindi è stato necessario meno tempo per eseguire l'operazione.

Perché la regex si comporta diversamente dove dovrebbe essere la stessa?

Martin

+0

Perché dovrebbe essere lo stesso? – BoltClock

+0

Credo che dovrebbe essere lo stesso perché fa la stessa cosa. Forse il compilatore ha bisogno di un'ottimizzazione quando la pipa viene utilizzata con un singolo carattere. – Martin

risposta

4

Il primo frammento di codice guarda attraverso bigBuffer due volte, la prima volta sostituendo le nuove linee, e la seconda volta sostituisce le linguette.

Il secondo snippet di codice eseguirà una ricerca su bigBuffer una sola volta, controllando se ciascun carattere è uno o l'altro. Ciò comporterebbe la velocità di finitura solo nella metà del tempo.

Lo snippet di codice nel terzo posto è probabilmente scarsamente compilato e risulta in una versione particolarmente negativa dell'algoritmo del primo codice, sebbene non potrei dire con certezza senza esaminare attentamente il percorso attraverso la compilazione di regex.

Ottimo lavoro sul test però. Il tempismo relativo (basato su percentuali) è utile, il tempo assoluto (millisecondo o alcuni di questi) non lo è.

2

In generale, una classe di caratteri ([abc]) tende ad essere più efficiente di un'alternativa equivalente (a|b|c), quindi non so perché il tuo amico lo suggerirebbe. Ma in Java, le classi di caratteri che corrispondono solo ai caratteri del repertorio Latin1 (vale a dire i primi 256 punti di codice Unicode) sono ulteriormente ottimizzate. Questo è probabilmente il motivo per cui stai vedendo una così grande differenza tra la seconda e la terza tecnica.

Ancora, questo è solo in Java. In Perl, mi aspetterei che la differenza tra l'alternanza e la classe di caratteri sia trascurabile, essendo un'implementazione molto più matura. E in grep sarebbe probabilmente difficile misurare la differenza, non importa quale dei tre approcci hai usato - è solo così veloce.

Ma come regola generale, se si ha una scelta tra l'uso di una classe di caratteri o un'alternanza, si dovrebbe preferire la classe di caratteri. Potrebbe non essere più veloce, ma sicuramente non sarà più lento. E l'uso improprio, l'alternanza può avere un effetto disastroso sulle prestazioni.

+0

Grazie per la regola generale, mi assicurerò che il mio amico lo sappia. – Martin

Problemi correlati