2012-01-17 11 views
6

In che modo le prestazioni di questi due metodi per determinare se una stringa inizia con una determinata sottostringa in Delphi confronta? Uno è significativamente più veloce/più efficiente dell'altro?L'efficienza delle tecniche "inizia con la sottostringa" in Delphi?

if ((testString[1] = '=') AND (testString[2] = '?')) then ... 

vs.

if (AnsiStartsStr('=?', testString)) then ... 
+4

valutazione da sinistra a destra non è richiesto per il primo metodo. È possibile regolarlo per filtrare prima le occorrenze meno frequenti. Ad esempio, è possibile verificare prima il punto interrogativo se fosse meno frequente. –

risposta

7

Bene, la prima sarà sicuramente più veloce. Risolvere un problema altamente specifico e codificato è quasi sempre molto più rapido che passare una soluzione specifica a una routine di risoluzione di problemi generali. Per quanto riguarda "significativamente" più veloce, perché non lo test? Esegui entrambe le versioni in un ciclo 10 milioni di volte e usa TStopwatch (o qualcos'altro se non hai D2010 o successivo) per cronometrare.

Un'altra cosa: il primo è decisamente più veloce, ma potrebbe anche essere sbagliato. Se non è garantito che length(TestString) sia> = 2, qui potrebbe esserci una condizione di errore. Se TestString è una stringa vuota, si genera un'eccezione. In caso contrario, potresti avere o meno un'eccezione a seconda delle impostazioni del compilatore.

+2

Buon punto. Il primo non è sempre sicuro. Richiede almeno 'if Length (testString)> = 2) e ...' –

+1

Anche la valutazione di cortocircuito dell'operatore AND è di grande aiuto, nei casi in cui non corrisponde. –

+0

@MarcusAdams Se hai trascurato l'aspetto LOCALE di 'AnsiStartsStr', quindi' AnsiStartsStr' potrebbe essere implementato con la stessa efficienza dell'esplicativo 'if' (sebbene quasi certamente non lo sia) –

2

Il primo nella finestra di CPU è solo mov, cmp e jnz (eventualmente ripetuto una sola volta), mentre il secondo sembra molto più complicato (usa Copy e Winapi di CompareString). In primo luogo dovrebbe essere più veloce.

+0

'AnsiStartsStr()' usando 'Copy()' internamente è una cattiva implementazione da parte di Borland, IMHO. Avrebbero potuto usare 'CompareString()' senza 'Copy()' come 'AnsiStartsText()' fa, basta chiamare 'CompareString()' con diversi flag. Peccato che CodeGear ed Embarcadero non l'abbiano mai aggiustato negli anni dopo che Borland aveva rinunciato alla proprietà dei suoi strumenti di sviluppo. –

+0

@ RemyLebeau-TeamB Il collo di bottiglia principale di 'AnsiStartsStr' non è l'uso interno di' copia', ma l'uso di 'AnsiSameStr' che chiama l'API di Windows' CompareString' molto lenta. In effetti, la maggior parte delle funzioni di 'Ansi *' chiama queste API e sono lente se l'intera gestione Unicode non è necessaria (ad esempio quando si usano i caratteri Ascii a 7 bit, cosa che accade molto nella programmazione). L'intero RTL è pieno di codice funzionante, ma non scritto per la velocità. Il mio preferito è l'implementazione di 'IntToStr', che è semplicemente dannatamente lento (anche più lento da Delphi 2009). –

4

Se avete bisogno di velocità con la flessibilità si può provare qualcosa di simile:

function StatsWith(const SubStr, Str: string): Boolean; inline; 
begin 
    if Length(SubStr) <= Length(Str) then 
    Result := CompareMem(Pointer(SubStr), Pointer(Str), ByteLength(SubStr)) 
    else 
    Result := False; 
end; 
+0

ByteLength() funzionerà con Delphi 2009+ solo io sospetto. 'length (SubStr) * sizeof (char)' è più standard. –

+1

@ArnaudBouchez Se non hai intenzione di supportare le vecchie versioni del compilatore, allora 'ByteLength' è più chiaro. –

+0

ByteLength è implementato (in D2010) come una funzione inline implementata come 'Length (s) * SizeOf (Char)' ... Comunque, potrebbe essere eccessivo, ma probabilmente andrei con 'Length (s) * StringElementSize (s) '. –

Problemi correlati