In C, le grandi "catene di puntatori" sono pessime per le prestazioni o la pulizia del codice?

3

Il seguente esempio:

i = readString(&packet->data.play_server.updatesign.line1, pbuf, ps);

Ha una grande quantità di strutture / unioni annidate. Questo è generalmente disapprovato nella pulizia del codice, o cattivo per le prestazioni?

    
posta JavaProphet 05.03.2016 - 17:47
fonte

1 risposta

4

Il cattivo rendimento è discutibile nel tuo esempio. Il vero dereferenziamento del puntatore del runtime in sequenza può essere negativo per la coerenza della cache. Ma il tuo esempio non lo mostra; ha solo un puntatore di runtime per dereferenziare.

C è un linguaggio tipizzato staticamente. Pertanto, al momento della compilazione, il compilatore conosce le dimensioni e il layout di ogni membro del subooggetto di ogni oggetto. Quindi .play_server.updatesign.line1 si basa fondamentalmente su un offset intero statico di un puntatore. Diventa &packet->data + static_offset (usando l'aggiunta di un byte piuttosto che l'aritmetica del puntatore a C).

Se quelli . s erano stati invece -> s, sarebbe stato diverso. Ciascun puntatore di questo tipo potrebbe in runtime avere un valore particolare. E quindi, il compilatore non può far bollire tutto fino a un offset statico; deve essere eseguito in runtime come una catena di accessi, ognuno dei quali legge un puntatore dall'oggetto successivo. E quindi, come iterando attraverso una lista collegata, può essere un errore per la coerenza della cache e così via.

Per quanto riguarda la pulizia del codice, tutto dipende piuttosto da dove ti trovi e da cosa stai facendo. Se packet->data è solo una semplice struttura di dati senza necessità di invarianti, allora va bene. Quei sottooggetti sono solo aggregati, non contenitori intelligenti che richiedono incapsulamento. Se all'interno di questa struttura dati c'è qualche invarianza, allora la modifica diretta di una tale struttura di dati violerebbe l'incapsulamento e quindi sarebbe pericolosa.

Quindi di nuovo, fornire l'incapsulamento in C di solito richiede dichiarazioni nascoste (dichiarazioni in avanti e così via), che tende a rendere difficile l'inlining. E se ognuno di questi accessi ai sottooggetti fosse un'azione incapsulata, ciò potrebbe rappresentare il tipo di "catena di puntatori" di cui si è interessati, dal momento che il compilatore non sarebbe facilmente in grado di compilare gli accessi fino a un offset statico. Quindi i programmi C tendono a impiegare l'incapsulamento ai confini dei principali sistemi o API, piuttosto che all'interno dei singoli sistemi stessi.

Ciò che è pulito per un programmatore non è pulito per un altro.

    
risposta data 05.03.2016 - 18:26
fonte

Leggi altre domande sui tag