L'AWL dovrebbe essere evitato in applicazioni di grandi dimensioni?

24

Questa potrebbe sembrare una domanda strana, ma nel mio reparto abbiamo problemi con la seguente situazione:

Lavoriamo qui su un'applicazione server, che sta diventando sempre più grande, anche al punto che stiamo pensando di suddividerla in parti diverse (file DLL), caricando dinamicamente quando necessario e scaricando in seguito, per essere in grado di gestire i problemi di prestazioni.

Ma: le funzioni che stiamo usando, stanno passando i parametri di input e output come oggetti STL e come menzionato in una risposta Overflow dello stack , questa è una pessima idea. (Il post contiene alcune ± soluzioni e hack, ma non sembra tutto molto solido.)

Ovviamente potremmo sostituire i parametri di input / output con i tipi standard di C ++ e creare oggetti STL da quelli una volta all'interno delle funzioni, ma questo potrebbe causare cali di prestazioni.

Va bene concludere che, nel caso in cui si stia pensando di creare un'applicazione, che potrebbe crescere così grande che un singolo PC non può più gestirlo, non si deve assolutamente usare STL come tecnologia?

Ulteriori informazioni su questa domanda:
Sembra che ci siano dei malintesi sulla domanda: il problema è il seguente:
La mia applicazione utilizza enormi quantità di prestazioni (CPU, memoria) per completare il suo lavoro e vorrei dividere questo lavoro in parti diverse (poiché il programma è già suddiviso in più funzioni), non è difficile creare DLL fuori dalla mia applicazione e inserire alcune delle funzioni nella tabella di esportazione di tali DLL. Ciò comporterebbe la seguente situazione:

+-----------+-----------+----
| Machine1  | Machine2  | ...
| App_Inst1 | App_Inst2 | ...
|           |           |    
| DLL1.1    | DLL2.1    | ...
| DLL1.2    | DLL2.2    | ...
| DLL1.x    | DLL2.x    | ...
+-----------+-----------+----

App_Inst1 è l'istanza dell'applicazione, installata su Machine1, mentre App_Inst2 è l'istanza della stessa applicazione, installata su Machine2.
DLL1.x è una DLL, installata su Machine1, mentre DLL2.x è una DLL, installata su Machine2.
DLLx.1 copre la funzione esportata1.
DLLx.2 copre la funzione esportata2.

Ora su Machine1 mi piacerebbe eseguire function1 e function2. So che questo sovraccaricherà Machine1, quindi mi piacerebbe inviare un messaggio a App_Inst2, chiedendo all'istanza dell'applicazione di eseguire function2.

I parametri di input / output di function1 e function2 sono oggetti STL (C ++ Standard Type Library), e regolarmente potrei aspettarmi che il cliente faccia gli aggiornamenti di App_Inst1, App_Inst2, DLLx.y (ma non tutti, il cliente potrebbe aggiornare Machine1 ma non Machine2, o solo aggiornare le applicazioni ma non le DLL o viceversa, ...). Ovviamente se l'interfaccia (parametri di input / output) cambia, allora il cliente è costretto a fare aggiornamenti completi.

Tuttavia, come menzionato nell'URL StackOverflow, una semplice ricompilazione di App_Inst1 o di una delle DLL potrebbe causare l'intero sistema a crollare, da qui il mio titolo originale di questo post, sconsiderando l'uso di STL ( Libreria di modelli standard C ++) per applicazioni di grandi dimensioni.

Spero di aver risolto alcune domande / dubbi.

    
posta Dominique 22.05.2018 - 09:35
fonte

7 risposte

109

Questo è un classico problema X-Y per la pietra.

Il tuo problema reale sono i problemi di prestazioni. Tuttavia, la tua domanda chiarisce che non hai effettuato alcuna profilazione o altre valutazioni su dove i problemi di rendimento provengono effettivamente. Invece speri che dividere il tuo codice in DLL risolverà magicamente il problema (che non sarà, per la cronaca), e ora sei preoccupato per un aspetto di quella non-soluzione.

Invece, è necessario risolvere il vero problema. Se disponi di più eseguibili, controlla quale sta causando il rallentamento. Mentre ci sei, assicurati che in realtà il tuo programma impieghi tutto il tempo di elaborazione e non un driver Ethernet mal configurato o qualcosa del genere. E dopo, inizia a profilare le varie attività nel tuo codice. Il timer ad alta precisione è tuo amico qui. La soluzione classica consiste nel monitorare i tempi di elaborazione medi e peggiori per un blocco di codice.

Quando hai i dati, puoi capire come affrontare il problema e poi puoi capire dove ottimizzare.

    
risposta data 22.05.2018 - 21:43
fonte
38

Se è necessario suddividere un software tra più macchine fisiche, è necessario disporre di una qualche forma di serializzazione quando si passano dati tra macchine, poiché solo in alcuni casi è possibile semplicemente inviare lo stesso binario esatto tra le macchine. La maggior parte dei metodi di serializzazione non ha problemi a gestire i tipi STL, quindi il caso non è qualcosa che mi preoccupi.

Se devi dividere un'applicazione in librerie condivise (DLL) (prima di farlo per motivi di prestazioni, dovresti davvero assicurarti che possa effettivamente risolvere i tuoi problemi di prestazioni) passare gli oggetti STL può essere un problema ma non ha essere. Come già descritto nel link che hai fornito, il passaggio degli oggetti STL funziona se usi lo stesso compilatore e le stesse impostazioni del compilatore. Se gli utenti forniscono le DLL, potresti non essere in grado di contare facilmente su questo. Se fornisci tutte le DLL e compili tutto insieme, allora potresti essere in grado di contare su di esse e utilizzare gli oggetti STL attraverso i confini della DLL diventa molto possibile. Devi ancora fare attenzione alle impostazioni del compilatore in modo da non ottenere più heap diversi se passi la proprietà dell'oggetto, anche se non si tratta di un problema specifico per STL.

    
risposta data 22.05.2018 - 10:00
fonte
20

We are working here on a server application, which is growing larger and larger, even at the point that we are considering to split it into different parts (DLLs), dynamically loading when needed and unloading afterwards, in order to be able to handle the performance issues

La RAM è economica e quindi il codice inattivo è economico. Il caricamento e lo scaricamento del codice (in particolare lo scarico) è un processo fragile ed è improbabile che abbia un impatto significativo sulle prestazioni dei programmi su hardware moderno desktop / server.

La cache è più costosa ma influisce solo sul codice che è attivo di recente, non sul codice che si trova nella memoria inutilizzato.

In generale i programmi superano i loro computer a causa delle dimensioni dei dati o del tempo della CPU, non della dimensione del codice. Se la dimensione del tuo codice diventa così grande da causare problemi importanti, probabilmente vorresti guardare al motivo per cui ciò sta accadendo in primo luogo.

But: the functions we are using, are passing input and output parameter as STL objects, and as mentioned in this StackOverflow URL, this is a very bad idea.

Dovrebbe essere ok fintanto che le DLL e l'eseguibile sono tutti compilati con lo stesso compilatore e collegati dinamicamente alla stessa libreria di runtime C ++. Ne consegue che se l'applicazione e le DLL associate vengono create e distribuite come un'unica unità, non dovrebbe essere un problema.

Dove può diventare un problema è quando le librerie sono costruite da persone diverse o possono essere aggiornate separatamente.

Is it ok to conclude that, in case you are considering to build an application, which might grow that large that one single PC can't handle it anymore, you must not use STL as a technology at all?

Non proprio.

Una volta che si inizia a distribuire un'applicazione su più macchine, si ha una serie di considerazioni su come si passano i dati tra tali macchine. I dettagli relativi all'utilizzo dei tipi di STL o di altri tipi di base potrebbero essere persi nel rumore.

    
risposta data 22.05.2018 - 15:31
fonte
13

No, non penso che segua questa conclusione. Anche se il tuo programma è distribuito su più macchine, non c'è motivo per cui l'uso del STL internamente ti costringa a usarlo nella comunicazione tra moduli e processi.

In effetti, direi che dovresti separare la progettazione delle interfacce esterne dall'implementazione interna dall'inizio, poiché la prima sarà più solida / difficile da cambiare rispetto a quella utilizzata internamente

    
risposta data 22.05.2018 - 10:00
fonte
7

Ti manca il punto di questa domanda.

Esistono fondamentalmente due tipi di DLL. Il tuo e quello di qualcun altro. Il "problema STL" è che tu e loro potresti non usare lo stesso compilatore. Ovviamente, questo non è un problema per la tua DLL.

    
risposta data 22.05.2018 - 23:54
fonte
5

Se costruisci le DLL dallo stesso albero dei sorgenti allo stesso tempo con lo stesso compilatore e le opzioni di compilazione, allora funzionerà OK.

Tuttavia il modo "Windows flavored" di dividere un'applicazione in più parti, alcune delle quali sono riutilizzabili è Componenti COM . Questi possono essere piccoli (singoli controlli o codec) o grandi (IE è disponibile come controllo COM, in mshtml.dll).

dynamically loading when needed and unloading afterwards

Per un'applicazione server, questa avrà probabilmente un'efficienza terribile ; è davvero fattibile solo quando hai un'applicazione che si muove attraverso più fasi per un lungo periodo di tempo in modo da sapere quando qualcosa non sarà più necessario. Mi ricorda i giochi DOS che usano il meccanismo di sovrapposizione.

Inoltre, se il tuo sistema di memoria virtuale funziona correttamente, lo gestirà automaticamente sfogliando le code page inutilizzate.

might grow that large that one single PC can't handle it anymore

Acquista un PC più grande.

Non dimenticare che con l'ottimizzazione giusta un laptop può sovraperformare un cluster hadoop.

Se veramente ha bisogno di più sistemi, devi pensare molto attentamente al confine tra loro, poiché è lì che si trova il costo della serializzazione. Qui è dove dovresti iniziare a guardare framework come MPI.

    
risposta data 22.05.2018 - 16:56
fonte
0

We are working here on a server application, which is growing larger and larger, even at the point that we are considering to split it into different parts (DLL files), dynamically loading when needed and unloading afterwards, in order to be able to handle the performance issues.

La prima parte ha senso (dividere l'applicazione su macchine diverse, per motivi di prestazioni).

La seconda parte (librerie di caricamento e scaricamento) non ha senso, poiché è uno sforzo extra da fare e non migliorerà (davvero) le cose.

Il problema che stai descrivendo è meglio risolto con macchine di calcolo dedicate, ma queste non dovrebbero funzionare con la stessa (principale) applicazione.

La soluzione classica ha questo aspetto:

[user] [front-end] [machine1] [common resources]
                   [machine2]
                   [machine3]

Tra le macchine di front-end e di calcolo, potresti avere cose extra, come bilanciamento del carico e monitoraggio delle prestazioni, e l'elaborazione specializzata su macchine dedicate è buona per l'ottimizzazione della cache e della velocità effettiva.

Questo non implica in alcun modo un caricamento / scaricamento extra delle DLL, né nulla a che fare con l'STL.

Cioè usa internamente STL come richiesto e serializza i tuoi dati tra gli elementi (vedi i buffer grpc e di protocollo e il tipo di problemi che risolvono).

Detto questo, con le informazioni limitate fornite, sembra il classico problema x-y (come ha detto @Graham).

    
risposta data 29.05.2018 - 16:10
fonte

Leggi altre domande sui tag