Con un focus predominante sulla programmazione a bassa latenza, probabilmente il C Programming Language di K & R è un po 'semplice e obsoleto. Ho ancora passione per quel libro, ma ora è più di un pezzo di storia. Forse sarebbe più utile studiare più di quei campi in tempo reale come l'elaborazione audio, i motori di gioco, la progettazione orientata ai dati, la programmazione di sistemi incorporati e semplicemente i libri più recenti sul linguaggio C.
Sono lontano da un esperto su questo argomento come uno che non ha mai affrontato i bisogni di latenza più esigenti e non ha mai programmato un sistema embedded (spero di non mettermi in imbarazzo qui), ma è un'estetica che apprezzo dal vedere " la media delle codebase C ++ nei campi critici per le prestazioni finisce per perdere rapidamente la reattività, solo per rivelare in una sessione di profilazione che questi tipi di misure hanno i loro hotspot distribuiti in tutto il luogo (lasciando alcuni punti critici da ottimizzare quando si cerca di ottimizzare per la reattività piuttosto) del throughput di una singola operazione pesante).
Un sacco di attenzione predominante che trovo nel mio campo, almeno, è la velocità effettiva con un focus sull'ottimizzazione di algoritmi ingombranti su dati omogenei. Molto sembra essere dimenticato di mantenere le cose altamente reattive per tutti i compiti disparati (o semplicemente piccoli) nel mezzo. Mi piace come ha detto Mike, che le costanti qui tendono ad essere altrettanto importanti della complessità algoritmica.
Tuttavia, la velocità effettiva, la latenza e la risposta deterministica sono per me un po 'sfocate. Ciò potrebbe essere notevolmente semplificato, ma al giorno d'oggi vedo problemi di latenza e, nel contesto di hardware muscoloso, avere a che fare con disparati compiti su dati non omogenei, con un focus sul throughput che pone un focus predominante su compiti uniformi su dati omogenei (qualsiasi compito che potrebbe essere ideale per la GPU come un esempio). Tecniche come il design orientato ai dati sono ancora potenzialmente applicabili alle richieste di latenza, ma con alcune modifiche.
Un modo per ottimizzare la latenza in questo tipo di prospettiva (probabilmente imperfetto) consiste nel riconoscere che l'omogeneità e persino i layout di memoria contigui (e quindi spesso la località di riferimento) sono spesso infranti da tipi di dati disparati. A livello di macchina, i dati assumono effettivamente dati omogenei e omogenei di bit e byte (anche se i requisiti di allineamento variano in base al tipo di registri e istruzioni utilizzati). Lo stack può memorizzare una combinazione di tipi di dati selvaggi per questo motivo, poiché è modellato a livello di bit e byte piuttosto che la nozione di un contenitore omogeneo di elementi (e un modo per migliorare la latenza è sfruttarne l'inferno). Capire questo può aiutarti a raggiungere il livello di allocatore di memoria personalizzato e iniziare a preallocare più tipi disparati di dati in blocco, raggruppandoli da un pool di memoria comune per fornire chunk di memoria richiesti per molti tipi di dati disparati.
In questo senso, stiamo ancora applicando quelle ingombranti mentalità progettuali orientate ai dati, ma appiattendo la disparità raggiungendo la nozione comune denominatore di bit e byte in memoria invece di "tipo di dati" (un meta concetto che è spesso cancellato per lo più in ogni caso in fase di runtime). Con questo tipo di aggiustamento, l'idea delle più tecniche focalizzate sul throughput e le tecniche focalizzate sulla latenza iniziano a confondersi sempre di più insieme, dal momento che stiamo riducendo la disparità di rappresentazione che può portare a singhiozzo nelle prestazioni.
Ci sono anche altre cose che aiutano semplicemente a bruciare più cicli, usando spin lock / loop CAS, cose del genere. Molte di queste tecniche sono spesso descritte come malvagie e con maggiore probabilità di essere utilizzate in modo abusivo piuttosto che utilizzate in modo appropriato, quindi possono entrare in molti argomenti tabù che portano a discussioni con altri sviluppatori (specialmente i più dogmatici) su ciò che è "giusto". Il mio suggerimento è semplicemente andare con quello che le misure e la responsività favoriscono. Simile a come insegnano gli artisti nella scuola d'arte, una volta che un artista diventa familiare e intimo con le regole classiche, allora è (ma solo allora) ha permesso di piegarle e romperle.
In ogni caso, il linguaggio di programmazione C di K & R non è probabilmente il miglior libro su questo tipo di argomenti (o persino l'apprendimento di C in generale), ma ci sono molte altre risorse. In realtà la programmazione in C può aiutare un bel po '. C e C ++, poiché le lingue possono condividere molto in comune l'una con l'altra al livello del denominatore comune, ma c'è un'estetica selvaggiamente diversa insieme alle pratiche idiomatiche. C può farti arrivare più velocemente allo stadio di bit e byte nudi, utile per migliorare la tua comprensione di concetti come l'efficienza della memoria, se non altro per l'estetica e le pratiche idiomatiche che promuove. L'estetica C ++ può essere un meraviglioso complemento a quello di fornire interfacce di alto livello, sicure, astratte e / o generiche su queste tecniche di ottimizzazione di basso livello che si applicano più a livello di implementazione.