struct

Salve ragazzi, è da un po che non scrivo, ma da qualche giorno sto rivedendo di sanapianta il codice di un progetto.
Volendo impostare la manipolazione dei dati con le struct volevo chiedervi se, a parte la comodità di utilizzare i dati strutturati, vi sia una differenza a livello prestazionale.
Grazie anticipatamente.

No
Forse

Ovvero:

No tutt'altro, siccome passi per un elemento in più, la struttura appunto, questo complica l'accesso ai dati

Forse, dato che un compilatore ottimizzante dovrebbe approfittare della maggiore regolarità dei dati, o almeno non peggiorare la situazione

Sì, nel senso che una forma dati strutturata fa "naturalmente" pensare in maniera più strutturata
E questo riduce la complessità di scrittura del codice, lo rende più corto, più lineare, più rapido da scrivere, e spesso anche più efficiente
Però se ti fermi solo al primo passo, non serve. È solo complicazione...

Più o meno la spiegazione del perché l'AI non sarà mai una mente umana... :smiley:
Proprio perché non ha il dono del "perché", saranno e rimarranno macchine mangiaByte per quanto potranno somigliare a noi!
Grazie Standardoil e condivido quello che hai listato. Sei stato molto chiaro nel spiegare, in due righe, che struct semplifica e giustifica i nostri ragionamenti a discapito delle risorse.
Per altri punti di vista attendo!

È impossibile dare una risposta generica, dipende da cosa ci vuoi fare. Però ti rigiro la domanda: cosa ci guadagni a non usarle?

Tieni conto che usare (bene) le struct è un passo verso la programmazione a oggetti, che oggi è il paradigma che va per la maggiore, e che sicuramente porta grandi benefici in termini di leggibilità, mantenibilità e riciclo del codice. Questi sono gli aspetti che bisognerebbe prediligere nella programmazione, invece di ricercare l'ottimizzazione esasperata a tutti i costi. Eventuali problemi di performance si affrontano in un secondo tempo tramite profiling del codice e ottimizzazioni mirate.

Diciamo che le pessimizzazioni sull'uso delle risorse derivanti dalle struct sono la pagliuzza rispetto alle travi derivanti da logiche sbarellate di più alto livello che si vedono in giro :wink:

Secondo me, anche senza aggiungerci cose tipiche della programmazione ad oggetti, ma semplicemente usandole come strumento per raggruppare e ordinare la struttura dati, può dare vantaggi notevoli riguardo alla manutenibilità.

maubarzi:
raggruppare e ordinare la struttura dati

Questa è esattamente la ragione prima che ha portato allo sviluppo della programmazione a oggetti ;).

Il passo successivo è metterci dentro anche le funzioni che manipolano i dati.

Tutto il resto degli aspetti tipici della OOP nasce da queste premesse.

#SukkoPera io personalmente, al momento, utilizzo struct perché avendo 3 "oggetti" per i quali devo dichiarare una serie di variabili comuni tra loro per funzione (ad esempio consensi, flag, millis, dato elaborato nel loop, dato trasmesso via wireless a termine del loop, ecc) diventa molto più leggibile e facile da listare il codice senza dover ricordare quale strambo nome gli abbia assegnato a quella variabile. Basta oggetto.variabile = xxx (più leggibile di così)
Per questo, UPpo la mia domanda iniziale. In termini prestazionali cambia poco/niente al micro, o ci sono addirittura dei decrementi prestazionali degni di nota per un semplice 328?

Si, però non necessariamente il codice di manipolazione deve essere inglobato nella struttura dati.
Poi con i vari paradigmi di programmazione risolvi gli stessi problemi in modo differente, quello che accomuna, in genere, è la necessità di dare una struttura, ai dati, facilmente gestibile, non tanto all'interno del codice ma proprio nella programmazione, per non rischiare di perdersi pezzi per strada quando i dati sono troppo sparpagliati.
Strucando strucando il concetto fino a porlo in termini pure troppo elementare e semplificativo.

SukkoPera:
Il passo successivo è metterci dentro anche le funzioni che manipolano i dati.

Proprio stamattina leggevo il post di standardoil delle funzioni all'interno delle struct. non pensavo fosse possibile... questo spalanca le porte ad altri orizzonti per me! Approfondirò!

EDIT: maubarzi il problema è che, ad esempio, ad esempio mentre stai elaborando il dato di un oggetto devi interdire dei consensi o flag di altri oggetti in alcune condizioni piuttosto che in altre. Quindi strutturando i dati è molto più difficile confondersi.

Si, è quello che dico io, aiuta a tenere sotto controllo le cose.

Ma perché dovrebbero esserci decrementi prestazionali? Cosa ti fa pensare ciò?

Anzi, aumenti anche lo località dei dati e quindi la CPU sfrutta meglio la cache!

(Dubito che il 328 abbia memoria cache, ma rende l'idea.)

Tieni conto che usare (bene) le struct è un passo verso la programmazione a oggetti, che oggi è il paradigma che va per la maggiore, e che sicuramente porta grandi benefici in termini di leggibilità, mantenibilità e riciclo del codice. Questi sono gli aspetti che bisognerebbe prediligere nella programmazione, invece di ricercare l'ottimizzazione esasperata a tutti i costi. Eventuali problemi di performance si affrontano in un secondo tempo tramite profiling del codice e ottimizzazioni mirate.

Quando dice (bene) intende anche di evitare di passare come argomenti oggetti pesanti a delle funzioni, meglio avere una o più istanza di struct globali, questo per lo stile arduino.

E non vedo perché dovrebbero peggiorare le prestazioni.

Non solo quello, anche perché non c'è niente di male se le passi by reference.

Maurotec:
Quando dice (bene) intende anche di evitare di passare come argomenti oggetti pesanti a delle funzioni, meglio avere una o più istanza di struct globali, questo per lo stile arduino.

E non vedo perché dovrebbero peggiorare le prestazioni.

questo è in contrasto con questo

Standardoil:
No tutt'altro, siccome passi per un elemento in più, la struttura appunto, questo complica l'accesso ai dati.

EDIT: Ecco perché mi piace il confronto...

Il fatto di mettere un oggetto in più,la struttura, con un operatore in più, il punto, complica certamente il programma
Poi compilatori 'furbi' sanno approfittarne, ma un compilatore 'generico' forse no

Ma quelli sono tutti problemi "sintattici". Immaginiamo una funzione che calcola la distanza tra due punti. Senza struct:

float dist (const float x1, const float y1, const float x2, const float y2);

Morale: 16 byte da pushare sullo stack. Con una struct:

struct Point {
  float x;
  float y;
};

float dist (const Point& p1, const Point& p2)

Morale: 2 indirizzi da pushare sullo stack, ovvero 4 byte su AVR.

In verità, è un discorso che lascia un po' il tempo che trova, perché - volendo fare le pulci - la calling convention AVR in realtà non prevede sempre di pushare gli argomenti sullo stack, e perché per accedere a y con la struct il compilatore dovrà perdere tempo a sommare un offset all'indirizzo. Per questo la verità è che il tutto dipende dall'utilizzo pratico che se ne fa. Quel che è evidente, però, è l'aumentata leggibilità che, come dicevo prima, dovrebbe essere la prima cosa da perseguire.

SukkoPera:
Quel che è evidente, però, è l'aumentata leggibilità che, come dicevo prima, dovrebbe essere la prima cosa da perseguire.

Ecco perché le preferisco in alcuni casi rispetto alle singole variabili.

SukkoPera:
Tieni conto che usare (bene) le struct è un passo verso la programmazione a oggetti, che oggi è il paradigma che va per la maggiore, e che sicuramente porta grandi benefici in termini di leggibilità, mantenibilità e riciclo del codice. Questi sono gli aspetti che bisognerebbe prediligere nella programmazione, invece di ricercare l'ottimizzazione esasperata a tutti i costi. Eventuali problemi di performance si affrontano in un secondo tempo tramite profiling del codice e ottimizzazioni mirate.

Quoto in toto.

Grazie a tutti per la partecipazione!
SukkoPera cosa intendi profiling del codice?
Come autorisposta che mi sono dato "riguardando il codice cercare di fare la stessa cosa ottimizzando risorse e tempistiche di esecuzione dei loop"...
ma è proprio questo il tuo riferimento?
Quindi non proprio adatto per guy copy & paste :smiley: (i sarti li chiamo, taglia e cuci :D)

miky_police:
SukkoPera cosa intendi profiling del codice?

Il tutto parte dall'osservazione che a priori è difficile stabilire davvero quali parti di codice saranno eseguite più frequentemente, quindi è inutile ottimizzare tutto sempre. Ovviamente bisogna strutturare bene il programma e usare il buon senso, ma fare i salti mortali per risparmiare un bit o mettersi a scrivere parti in assembly a caso spesso risulta inutile, soprattutto se va a scapito della leggibilità, mantenibilità e portabilità, come già detto.

Una volta che il codice è completo, si valuta se ci sono problemi di performance o meno. Qualora si desideri migliorarle, si fa il profiling. Ora, non ho idea di come si possa fare nel contesto di Arduino, in ogni caso si tratta di strumentare il codice (tramite un apposito tool, mica a mano) in modo che registri informazioni su quali funzioni vengono chiamate e quando. A posteriori, si analizzano queste informazioni e si vede, ad esempio, che la funzione X() è stata chiamata miliardi di volte, quando magari ci si aspettava molte meno. Dunque si agisce di conseguenza, sistemando il problema o ottimizzando X(), che ora sappiamo essere un punto critico, cosa probabilmente difficile da prevedere.

You get the idea :).