Vediamo... controlliamo il codice compilato (
https://godbolt.org/ utilizzo il compilatore gcc e come target platform scelgo x86_64):
La prima funzione viene compilata nel seguente codice Assembly:
Codice:
strlen(char*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-24], rdi
mov rax, QWORD PTR [rbp-24]
mov QWORD PTR [rbp-8], rax
jmp .L2
.L3:
add QWORD PTR [rbp-8], 1
.L2:
mov rax, QWORD PTR [rbp-8]
movzx eax, BYTE PTR [rax]
test al, al
jne .L3
mov rax, QWORD PTR [rbp-8]
sub rax, QWORD PTR [rbp-24]
pop rbp
ret
Nella seconda funzione ho dovuto correggere prima due errori:
1. La condizione del while (linea 4) deve essere
ovvero avevi mancato l'asterisco.
2. Dopo il while ci vogliono le parentesi graffe perché occorre un blocco di 2 istruzioni e non una singola istruzione, ovvero deve essere così:
C:
while(*s != '\0') {
x++;
s++;
}
Dopo aver corretto questi due errori, procediamo a dare il codice in pasto al nostro compilatore di fiducia:
Codice:
strlen(char*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-4], 0
jmp .L2
.L3:
add DWORD PTR [rbp-4], 1
add QWORD PTR [rbp-24], 1
.L2:
mov rax, QWORD PTR [rbp-24]
movzx eax, BYTE PTR [rax]
test al, al
jne .L3
mov eax, DWORD PTR [rbp-4]
sub eax, 1
pop rbp
ret
Le prime tre righe e le ultime due di ambedue le routine sono standard per le funzioni C.
Il nucleo delle funzioni è ciò che vi è in mezzo.
Ora considera questo: in generale, la CPU fa i calcoli in maniera estremamente veloce mentre legge dalla memoria in maniera estremamente lenta.
Ora io vedo che la prima routine accede alla memoria (in scrittura o lettura) tramite le istruzioni mov e add 6 volte (3 volte nel loop e 3 volte fuori dal loop).
La seconda routine, invece, accede alla memoria 4 volte nel loop e 2 volte fuori dal loop. Ovvero potenzialmente è più lenta.
Occorre anche considerare che per 1 istruzione mov in più non è che cambi molto. Anche perché le CPU di oggi hanno anche le cache che ottimizzano i tempi di accesso in memoria.
Secondo me, più che concentrarsi sul fatto che una funzione impeghi 1 clock di CPU in più occorre concentrarsi dapprima sull'efficacia del software: ovvero scrivere codice che fa ciò che vogliamo che faccia. Ad esempio, prima ho individuato subito due bug nella seconda funzione che non l'avrebbero fatta funzionare come ci si aspettava.
Una volta che il codice funziona come vogliamo, possiamo pensare di ottimizzare rendendolo più efficiente/rapido.
My 2 cents