Quando dovrei preoccuparmi delle prestazioni?


16

Per molto tempo in luoghi come il canale IRC di Java , SO e altri luoghi, mi è stato detto qualcosa sulla falsariga di "Preoccuparsi di come appare il codice e della sua leggibilità / comprensibilità ora, e delle prestazioni in seguito se assolutamente necessario". Quindi, per molto tempo, non ho mai avuto un disturbo ossessivo-compulsivo riguardo alle prestazioni per le mie piccole applicazioni desktop o Web, ma ho semplicemente rimosso l'ovvio inefficiente.

La maggior parte delle risposte sono "Che dire della scalabilità?". Questo è un punto legittimo, ma se la mia app è stata creata solo per analizzare, diciamo, file lunghi 10.000 righe, dovrei rendere il mio codice un disastro per la piccola percentuale di persone che inseriranno un file da 1.000.000 di righe?

La mia domanda principale è quando dovrei scambiare i modi semplici ma in qualche modo inefficienti di svolgere compiti per grandi bestie complicate giganti che fanno le cose molto rapidamente ma distruggono ogni possibile modo di aggiornare e rendere il codice eccessivamente difficile e incline a riscrivere comunque dal prossimo sviluppatore?

Risposte:


23

Preoccupati per le prestazioni quando diventa un problema.

Se si scrive una piccola app per elaborare 10.000 file di linea e si ottiene un file di 1.000.000 di righe ogni 100 ° file, probabilmente non importa che ci vuole più tempo per elaborare quel file. Tuttavia, se ricevi regolarmente file che sono 5-10 volte più grandi di quelli iniziali e la tua applicazione impiega troppo tempo a fare il suo lavoro, allora inizi a profilare e ottimizzare.

Ora, ho detto "troppo tempo per fare il suo lavoro". Spetta all'utente o all'organizzazione sponsor decidere. Se sto eseguendo un'attività e mi ci vogliono 5 minuti per fare qualcosa quando mi ci sono voluti 3 senza il software o con uno strumento diverso, probabilmente presenterei una segnalazione di bug o una richiesta di manutenzione per migliorarla.

Se sei l'utente, quanto tempo vuoi che il tuo software impieghi a fare il suo lavoro dipende da te - solo tu puoi decidere se lo vuoi fare più velocemente o se sei disposto ad aspettare più a lungo per avere un codice più leggibile.



Inizio la profilazione e l'ottimizzazione Se 1) il lavoro impiega troppo tempo 2) una delle risorse hardware è al massimo (es. 100% CPU)
A. Binzxxxxxx

10

La mia domanda principale è quando dovrei scambiare i modi semplici ma in qualche modo inefficienti di svolgere compiti per grandi bestie complicate giganti che fanno le cose molto rapidamente ma distruggono ogni possibile modo di aggiornare e rendere il codice eccessivamente difficile e incline a riscrivere comunque dal prossimo sviluppatore?

Questa è generalmente una falsa dicotomia . Puoi scrivere codice meravigliosamente efficiente, leggibile e gestibile. Puoi scrivere pile di casino meravigliosamente inefficienti, non mantenibili.

Quando ho a che fare con problemi di prestazioni, di solito provo a pensare al problema aziendale che sto risolvendo. Come si comporterà il mio software quando lo usano i miei clienti. Le prestazioni delle mie applicazioni renderanno felice Jacob Nielsen ?


5
++ FICHI DICHOTOMIA! Non impareranno mai? Quando trovi e risolvi un problema di prestazioni, il codice non è solo più veloce, è meglio . Mi dispiace solo di avere un solo voto da dare!
Mike Dunlavey,

+1 per aver scritto che di solito è una falsa dicotomia ... non sempre, ma di solito.
Dan Rosenstark,

1
-1 per la scrittura è di solito una falsa dicotomia - il fatto è, di solito è corretto, e solo in rari casi una falsa dicotomia. In più di 30 anni della mia carriera di programmatore ho visto troppe ottimizzazioni delle prestazioni "ben intenzionate" che in effetti rendevano il codice più difficile da capire e mantenere (e spesso ottimizzavano qualcosa che era totalmente inutile per essere ottimizzato).
Doc Brown,

5

Una verità che ho scoperto studiando microprocessori al college che è rimasta con me: "Rendi veloce il caso comune. Rendi corretto il caso non comune."

Finché hai solo una piccola percentuale di utenti che soffoca il tuo codice con input di due ordini di grandezza più grandi di quello che doveva gestire, non sudare. Assicurati che gestisca correttamente l'input se lo danno abbastanza a lungo e non lascia nulla di corrotto in inutilità se uccide il lavoro prima che finisca.

Ma una volta sempre più persone iniziano a usarlo in questo modo (o iniziano a dirti "Sai, mi piacerebbe moltissimo usare lo strumento che hai scritto sui miei rapporti settimanali su TPS, ma ci vuole tutto il giorno stranamente"), ecco quando inizi a considerare la possibilità di scambiare facilità di manutenzione per ottenere miglioramenti delle prestazioni.


1

La mia domanda principale è quando dovrei scambiare i modi semplici ma in qualche modo inefficienti di svolgere compiti per grandi bestie complicate giganti che fanno le cose molto rapidamente ma distruggono ogni possibile modo di aggiornare e rendere il codice eccessivamente difficile e incline a riscrivere comunque dal prossimo sviluppatore?

"Preoccuparsi di come appare il codice e della sua leggibilità / comprensibilità ora, e delle prestazioni in seguito, se assolutamente necessario" è la via d'uscita facile e generalmente inutile. un buon design sarà facile da mantenere, facile da leggere ed efficiente.

le prestazioni sono un componente comune di un buon design. se il tuo programma è lento e dispendioso, in realtà non è riutilizzabile. quando devi correggere quel casino, imponi aggiornamenti ai tuoi client, a meno che non sia troppo tempo per convincerli ad aggiornare. quel programma lento diventa un gran casino che è troppo costoso per migliorare. quindi scelgono un'alternativa perché non soddisfa i loro bisogni. la diagnosi, l'aggiornamento e la gestione degli effetti collaterali dei miglioramenti di una cattiva progettazione spesso superano il tempo di sviluppo iniziale della sua scrittura per essere efficiente, funzionare correttamente e avere una progettazione genuinamente buona. quel programma è altamente riutilizzabile e richiede poca manutenzione (vincita).

quindi, la risposta breve alla tua domanda è "non sprecare. scrivere per il riutilizzo. va bene essere pigri quando si prototipano / sviluppano prove di concetti, ma non usare quel prototipo per il codice di produzione".

essere consapevoli ed evitare progetti inutili quando si scrivono programmi di produzione e programmi che si intende riutilizzare. durante l'implementazione è il momento ideale per scrivere il tuo programma in modo da non essere dispendioso: hai una chiara idea dei dettagli e del suo funzionamento, ed è davvero doloroso e inefficace da correggere dopo che è stato scritto. molte persone credono che un po 'di profilazione (forse) alla fine o se c'è un problema sia adeguato, quando di solito è troppo tempo per riprogettare / cambiare e le inefficienze sono così tante e così diffuse che non capisci il programma ben basato sui risultati di un profilo. questo approccio richiede poco tempo durante l'implementazione e (supponendo di averlo fatto abbastanza volte) si traduce in genere in una progettazione che è molte volte più veloce ed è riutilizzabile in molti più contesti. non essere dispendioso, scegliere buoni algoritmi, riflettere sulle tue implementazioni e riutilizzare le giuste implementazioni sono tutti componenti di una buona progettazione; tuttemigliora la leggibilità, la manutenibilità e il riutilizzo più spesso di quanto non faccia male.


0

Cerco di rendere leggibile il codice - le prestazioni sono dannate.

Quando e se il codice si rivelerà troppo lento, lo refatterò per essere più veloce. Di solito il processo di refactoring è seguito da molti commenti poiché il codice tende ad essere meno leggibile.


0

Um - Mai?

Scherzi a parte, il codice dovrebbe sempre essere scritto in modo da essere facilmente compreso e mantenuto.

Per quanto riguarda quando affrontare i problemi di prestazioni, gestiscili dopo averli identificati, non pre-ottimizzare il tuo codice perché poi indovinerai solo dove si trovano i problemi di prestazioni.

Se il tuo codice è scritto in modo da essere chiaro, conciso, comprensibile e gestibile, tu o un altro programmatore non dovreste avere problemi a riformattare il codice per renderlo più efficiente.


3
Non sono d'accordo con questo. Un requisito di prestazione è un requisito non funzionale valido per un sistema.
Thomas Owens

Tecnicamente se esiste un requisito relativo alle prestazioni chiaramente definito, si potrebbe dire che hai identificato un problema di prestazioni e devi tenerlo conto nella tua soluzione. Quello di cui sto parlando è diventare intelligente in anticipo in modo da poter evitare problemi "potenziali" non specifici.
Noah Goodrich,

Ah. Sì, hai assolutamente ragione in quel caso. Non ti preoccupare delle possibilità perché ce ne sono così tante, ma concentrati su ciò che sai.
Thomas Owens

0

Normalmente scrivo il codice per essere innanzitutto leggibile. Se, e solo se, trovo che il programma funzioni troppo lentamente per fare il suo lavoro, faccio un profilo e ottimizzo. Detto questo, non c'è nulla di sbagliato nel prendere l'abitudine di eseguire ottimizzazioni comuni che non influiscono sulla leggibilità del codice. Cioè, se un pezzo di codice può essere scritto in due modi ugualmente (o quasi ugualmente leggibili), scegli quello che di solito è più veloce.

Ad esempio, in Python, le comprensioni (o le espressioni del generatore) tendono ad essere più veloci del forciclo equivalente , quindi uso le comprensioni delle liste dove posso, se non influiscono sulla leggibilità (ad esempio, non annido le comprensioni delle liste se Posso evitarlo e usare invece un ciclo for perché le comprensioni dell'elenco nidificato possono essere difficili da analizzare mentalmente).

Allo stesso modo, i tipi di dati immutabili tendono ad essere più veloci di quelli mutabili, quindi uso tipi di dati immutabili dove posso.


0

Se lavori in aree veramente critiche per le prestazioni, non puoi rimandare l'efficienza come ripensamento. È una delle cose più importanti a cui pensare quando si progetta in anticipo in quei casi e in modi che riguardano la manutenibilità del risultato finale.

Non è possibile progettare e implementare un server su larga scala e iniziare a scrivere un codice semplice e ben documentato che utilizza solo funzioni di blocco per tutto con un blocco thread globale che blocca l'intero sistema per elaborare ogni singola richiesta client senza inserire alcuna pensato in qualsiasi stato condiviso, contesa sui thread e asincronicità. Tale è una ricetta per il disastro e la necessità di ridisegnare e riscrivere la maggior parte del codice ben documentato che hai scritto in modi che potrebbero portare alla base di codice più difficile da mantenere immaginabile, afflitta da condizioni di gara e deadlock a causa del tentativo per ottenere l'efficienza necessaria col senno di poi, invece di aver pensato in anticipo a progetti efficienti, semplici e funzionanti.

Un team di sviluppo del gioco a 8 mesi dalla produzione con un motore che va solo 2 frame al secondo sul proprio hardware più ape con 32 core mentre ha la tendenza a fermarsi per 15 secondi ogni volta che lo schermo è occupato è improbabile che ottenga immediatamente un prodotto utilizzabile solo riparare un piccolo hotspot localizzato. È probabile che il loro design sia FUBAR in modi che giustificano una rivisitazione epica del tavolo da disegno e modifiche del design che potrebbero precipitare in ogni angolo della base di codice.

Con John Carmack, ha parlato una volta di come deve essere eseguita una demo di tecnologia da un minimo di centinaia a migliaia di frame al secondo per integrarla nella produzione. Non è un'ossessione malsana per l'efficienza. Sa in anticipo che i giochi devono funzionare, nella loro interezza, a 30+ FPS affinché i clienti lo trovino accettabile. Di conseguenza un piccolo aspetto come un sistema di ombreggiatura sfumata non può essere eseguito a 30 FPS, altrimenti il ​​gioco nel suo insieme non può essere abbastanza veloce da fornire il feedback in tempo reale richiesto. È inutilizzabile fino a quando non raggiunge l'efficienza richiesta. In tali settori critici per le prestazioni in cui esiste un requisito fondamentale per l'efficienza, una soluzione che non riesce a raggiungere una velocità adeguata non è in realtà migliore di una che non funziona affatto,. E non è possibile progettare un sistema di ombreggiatura sfumata efficiente che gira da centinaia a migliaia di fotogrammi al secondo, come richiesto per un motore di gioco in tempo reale, a meno che non si metta in primo piano una quantità predominante di pensiero sulla sua efficienza. In effetti, in questi casi, il 90 +% del lavoro è orientato all'efficienza poiché è banale trovare un sistema di ombreggiatura sfumata che funziona bene a 2 ore per fotogramma usando il tracciato del percorso, ma non puoi aspettarti di sintonizzarlo a funzionare a centinaia di frame al secondo senza un cambio di approccio totalmente diverso.

Quando l'efficienza è una parte fondamentale della progettazione di un'applicazione, non ci si può aspettare di raggiungere l'efficienza col senno di poi senza perdere notevolmente più tempo di quanto si è risparmiato ignorandola, dal momento che non ci si può aspettare di realizzare un progetto funzionante con il senno di poi. Nessuno dice: " Va bene rimandare a pensare al design fino a tardi. Basta documentare bene il codice e in seguito è possibile elaborare un design adeguato ". Ma nelle architetture critiche per le prestazioni, questo è ciò che stai effettivamente facendo se non metti molta cura e pensiero in progetti efficienti in anticipo.

Questo non significa che devi mettere a punto le tue implementazioni fin dall'inizio. Per i dettagli dell'implementazione, c'è molto spazio per passare a soluzioni più veloci dopo la misurazione, a condizione che il design non debba cambiare, e spesso questo è il modo più produttivo per procedere. Ma a livello di progettazione, ciò significa che devi riflettere a sufficienza su come il design e l'architettura saranno in relazione con l'efficienza sin dall'inizio.

La differenza chiave qui è il design. Non è facile apportare grandi cambiamenti ai progetti con il senno di poi poiché i progetti accumulano dipendenze e le dipendenze si romperanno se il progetto cambia. E se un progetto ha un requisito per essere ragionevolmente efficiente o, in alcuni casi, che la sua qualità è ampiamente misurata dalla sua efficienza, allora non dovresti aspettarti di essere in grado di ottenere un design adeguato come ripensamento. Con qualsiasi prodotto competitivo in cui l'efficienza è un aspetto enorme della qualità, che si tratti di sistemi operativi o compilatori o processori video o raytracer o motori di gioco o motori fisici, i pensieri sull'efficienza e la rappresentazione dei dati sono stati meticolosamente pensati fin dall'inizio. E in quei casi non è prematura l'ottimizzazione di mettere così tanto in primo piano l'efficienza. Stava ponendo questo pensiero esattamente nel momento più produttivo per farlo,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.