Quando dovrei preoccuparmi delle prestazioni?

15

Per il tempo più lungo in luoghi come canale IRC di Java , SO, e in altri luoghi mi è stato detto qualcosa lungo le righe di "Preoccuparsi di come appare il codice e della sua leggibilità / comprensibilità ora, e prestazioni più tardi se assolutamente necessario". Quindi, per molto tempo, non sono stato OCD delle prestazioni per le mie piccole app desktop o web, rimuovendo semplicemente l'inefficienza.

La maggior parte delle risposte sono "Che cosa si può dire della scalabilità?". Questo è un punto legittimo, ma se la mia app è stata creata solo per analizzare, ad esempio, i file di 10.000 righe, dovrei rendere il mio codice un disastro per la piccola percentuale di persone che andranno a spingere su un file di 1.000.000 righe?

La mia domanda principale è quando dovrei scambiare i modi facili ma in qualche modo inefficienti di eseguire compiti per giganteschi animali giganteschi che fanno cose estremamente velocemente ma distruggono tutti i modi possibili di aggiornamento e rendono il codice eccessivamente difficile e incline a riscrivere comunque dal prossimo sviluppatore?

    
posta TheLQ 01.09.2010 - 23:19
fonte

8 risposte

23

Preoccupati delle 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 è necessario impiegare più tempo per elaborare quel file. Tuttavia, se ricevi regolarmente file che sono 5-10 volte più grandi di quanto inizialmente e la tua applicazione impiega troppo tempo per svolgere il proprio lavoro, allora inizi a profilare e ottimizzare.

Ora, ho detto "troppo a lungo per fare il suo lavoro". Spetta all'utente o all'organizzazione che sponsorizza decidere. Se sto svolgendo un'attività e mi occorrono 5 minuti per fare qualcosa quando mi ci sono voluto 3 senza il software o con uno strumento diverso, probabilmente avrei archiviato una segnalazione di bug o una richiesta di manutenzione per migliorarla.

Se sei l'utente, la durata del tuo software per svolgere il suo compito dipende da te, solo tu puoi decidere se vuoi farlo più velocemente o se desideri aspettare più a lungo per avere un codice più leggibile.

    
risposta data 01.09.2010 - 23:26
fonte
11

My main question is when should I trade the easy but somewhat inefficient ways of doing tasks for big giant complicated beasts that do things extremely quickly but destroy any possible ways of upgrading and make the code excessively difficult and prone to rewriting anyway by the next developer?

Di solito è una falsa dicotomia . Puoi scrivere codice straordinariamente efficiente, leggibile e manutenibile. Puoi scrivere meravigliosamente pile di pasticcio inefficienti e non mantenibili.

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

    
risposta data 02.09.2010 - 02:18
fonte
5

Una verità che ho imparato a studiare i microprocessori al college che sono rimasti con me: "Fai in modo che il caso comune sia veloce. Rendi corretto il caso insolito."

Se hai solo una piccola percentuale di utenti che soffocano il tuo codice con input di due ordini di grandezza più grandi di quello che era destinato a gestire, non preoccuparti. Assicurati di gestire correttamente l'input se lo danno abbastanza a lungo, e non lascia nulla di corrotto nell'inutilità se uccide il lavoro prima che finisca.

Ma, sempre più persone iniziano a usarlo in quel modo (o iniziano a dirti "Sai, mi piacerebbe molto usare lo strumento che hai scritto sui miei rapporti TPS settimanali, ma ci vuole tutto il giorno") , questo è il momento in cui inizi a considerare la facilità di manutenzione per i guadagni in termini di prestazioni.

    
risposta data 02.09.2010 - 16:13
fonte
1

My main question is when should I trade the easy but somewhat inefficient ways of doing tasks for big giant complicated beasts that do things extremely quickly but destroy any possible ways of upgrading and make the code excessively difficult and prone to rewriting anyway by the next developer?

"Preoccupati di come appare il codice e della sua leggibilità / comprensibilità ora, e le prestazioni in un secondo momento 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 una componente comune di un buon design. se il tuo programma è lento e dispendioso, non è davvero riutilizzabile. quando hai bisogno di sistemare quel pasticcio, imponi aggiornamenti sui tuoi client, a meno che non sia troppo tempo per loro di aggiornarli. quel programma lento diventa il gran casino che è troppo costoso per migliorare. quindi scelgono un'alternativa perché non soddisfa i loro bisogni. diagnosticare, aggiornare e gestire gli effetti collaterali dei miglioramenti apportati a un design scadente spesso superano il tempo di sviluppo iniziale di scrittura efficiente, lavoro corretto e design genrally. quel programma è altamente riutilizzabile e richiede una manutenzione ridotta (vinci).

quindi, la risposta breve alla tua domanda è "non essere dispendioso, scrivi per il riutilizzo, è normale essere pigri durante la prototipazione / lo sviluppo di bozze di concetti, ma non usare quel prototipo per il codice di produzione".

è importante conoscere ed evitare progettazioni inutili quando si scrivono programmi e programmi di produzione che si intende riutilizzare. durante l'implementazione è il momento ideale per scrivere il tuo programma in modo da non sprecare - hai una chiara idea dei dettagli e del suo funzionamento, ed è davvero doloroso e inefficace risolvere dopo che è stato scritto. molte persone credono che un piccolo profilo (forse) alla fine o se c'è un problema sia adeguato, quando di solito è troppo dispendioso in termini di tempo per riprogettare / cambiare e le inefficienze sono così numerose e così diffuse che non si capisce il programma ben basato sui risultati di un profilo. questo approccio richiede poco tempo durante l'implementazione e (supponendo che tu abbia fatto abbastanza volte) di solito si traduce in un design che è molto più veloce ed è riutilizzabile in molti altri contesti. non sprecare, scegliere buoni algoritmi, pensare alle implementazioni e riutilizzare le giuste implementazioni sono tutte componenti del buon design; tutti i quali migliorano la leggibilità, la manutenibilità e il riutilizzo più spesso di quanto non facciano male.

    
risposta data 27.09.2011 - 12:52
fonte
0

Cerco di rendere leggibile il codice: le prestazioni vanno maledette.

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

    
risposta data 01.09.2010 - 23:25
fonte
0

Um - Mai?

Seriamente, il codice dovrebbe sempre essere scritto in modo da essere facilmente compreso e mantenuto.

Riguardo a quando affrontare i problemi di prestazioni, gestiscili una volta che li hai identificati, non pre-ottimizzare il tuo codice perché allora ti starai solo chiedendo dove sono i problemi di prestazioni.

Se il tuo codice è scritto in modo da essere chiaro, conciso, comprensibile e mantenibile, tu o un altro programmatore non dovresti avere alcun problema nel refactoring del codice per renderlo più efficiente.

    
risposta data 01.09.2010 - 23:28
fonte
0

Normalmente scrivo codice per essere leggibile prima di tutto. Se, e solo se, trovo che il programma esegue troppo lento per fare il suo lavoro, faccio il profilo e l'ottimizzazione. Detto questo, non c'è niente di sbagliato nell'ottenere l'abitudine di eseguire ottimizzazioni comuni che non influenzano la leggibilità del tuo 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 list comprehensions (o espressioni generatrici) tendono ad essere più veloci del loop for equivalente, quindi uso le list comprehensions dove posso, se non influenzano la leggibilità (ad esempio, io 'n novo le comprensioni delle liste se posso evitarlo, e uso un ciclo for invece perché le intese delle liste annidate possono essere difficili da analizzare mentalmente).

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

    
risposta data 02.09.2010 - 00:21
fonte
0

Se lavori in aree veramente critiche per le prestazioni, non puoi rinunciare all'efficienza come un ripensamento. È una delle cose più importanti da considerare quando si progettano 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 semplicemente a scrivere codice semplice e ben documentato che utilizza solo funzioni di blocco per tutto ciò con un blocco thread globale che blocca l'intero sistema per elaborare ogni singola richiesta client mentre non ponendo alcun pensiero in uno stato condiviso, in un conflitto di argomenti e in un'asincronicità. Questa è una ricetta per il disastro e la necessità di riprogettare e riscrivere la maggior parte del codice ben documentato che hai scritto in modi che potrebbero portare alla base di codice più difficile da immaginare, afflitta da condizioni di gara e deadlock come risultato del tentativo per ottenere l'efficienza richiesta a posteriori, al contrario di avere semplicemente pensato a progetti efficienti, semplici e funzionanti in anticipo.

Un team di sviluppo di videogiochi 8 mesi in produzione con un motore che va a 2 fotogrammi al secondo sull'hardware più beeo con 32 core, mentre la tendenza a fermarsi per 15 secondi ogni volta che lo schermo è occupato è improbabile che ottenga immediatamente un utilizzo prodotto fissando solo un piccolo hotspot localizzato. È probabile che il loro design sia FUBAR in modi che garantiscano una rivisitazione epica del tavolo da disegno e modifiche al progetto che potrebbero sovrapporsi a ogni angolo del codice base.

Con John Carmack, ha parlato una volta di come una demo tecnologica deve funzionare al minimo da centinaia a migliaia di frame al secondo per integrarla nella produzione. Questa non è un'ossessione malsana per l'efficienza. Sa in anticipo che i giochi devono essere eseguiti, nella loro interezza, a 30+ FPS affinché i clienti lo trovino accettabile. Di conseguenza, un piccolo aspetto come un sistema di ombre morbide non può essere eseguito a 30 FPS, altrimenti il gioco nel suo complesso non può essere abbastanza veloce da fornire il feedback in tempo reale richiesto. È inutilizzabile fino a quando non raggiunge l'efficienza richiesta. In tali aree critiche per le prestazioni in cui vi è un requisito fondamentale per l'efficienza, una soluzione che non riesce a raggiungere una velocità adeguata non è in realtà migliore di quella che non funziona affatto, poiché entrambi sono completamente inutilizzabili . E non è possibile progettare un efficiente sistema di ombre morbide che funzioni 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à di pensiero predominante sulla sua efficienza. Infatti, in questi casi, il 90% del lavoro è orientato all'efficienza poiché è banale trovare un sistema di ombre morbide che funzioni bene a 2 ore per frame usando il tracciamento dei percorsi, ma non ci si può aspettare di sintonizzarlo per funzionare a centinaia di fotogrammi al secondo senza un cambio di approccio completamente diverso.

Quando l'efficienza è una parte fondamentale del design di un'applicazione, non ci si può aspettare di ottenere un'efficienza con il senno di poi senza perdere molto più tempo di quanto si è risparmiato ignorandola, dal momento che non si può pretendere di ottenere un design funzionante a posteriori. Nessuno dice: "Io sono d'accordo a rimandare il pensiero sul design solo più tardi. Basta documentare bene il codice e si può trovare un design adeguato più tardi ." Ma in architetture critiche per le prestazioni, è quello che stai facendo in modo efficace se non metti molta cura e attenzione in progetti efficienti in anticipo.

Ora questo non significa che devi mettere a punto le tue implementazioni in modo immediato. Per i dettagli di implementazione, c'è molto spazio per scorrere le soluzioni più veloci dopo la misurazione, a condizione che il design non debba essere modificato, e spesso questo è il modo più produttivo per farlo. Ma a livello di progettazione, significa che devi mettere la riflessione sufficiente su come il design e l'architettura si relazioneranno all'efficienza fin dall'inizio.

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

    
risposta data 08.12.2017 - 03:59
fonte

Leggi altre domande sui tag