2011-01-20 10 views
7

Ho un'applicazione C++ in cui la funzione "cancella" è lenta da eseguire. Cosa potrebbe causare questo e dove dovrei iniziare la mia ricerca di una soluzione?C++ "delete" è lento. Dove dovrei guardare prima?

Background: codice

Questa C++ è in un file ARX in esecuzione all'interno di AutoCAD, che è fondamentalmente solo una DLL.

Il computer specifico in cui l'eliminazione è lenta esegue AutoCAD 2011, Windows 7, 64-bit. Gli ARX per AutoCAD 2011 devono essere compilati utilizzando Visual Studio 2008 Service Pack 1.

Il computer con il problema è il computer di un cliente. Non ha alcuna versione di Visual Studio installata su di esso.

Sul mio computer di sviluppo, il codice non ha alcun problema in AutoCAD 2011.

Per provare, ho un po 'di codice che elimina una lista collegata. Sul computer con il problema, occorrono 0,7 secondi per eliminare l'elenco. Nei computer e nelle configurazioni senza problemi, lo stesso codice richiede 0,02 secondi. I tempi specifici non sono importanti - il grande diverso tra i due numeri è.

Ho fatto in modo di eseguire la stessa versione del codice su entrambi i computer, quindi non è un problema di rilascio contro il debug build.

+1

Quanti oggetti c'erano nella lista e qual era la loro dimensione? –

+2

Condividi il codice di prova che stai usando per il benchmark. – karlphillip

+0

E stai collegando staticamente/dinamicamente su entrambi i sistemi? E per favore conferma che non stai confrontando le build di debug/release? –

risposta

5

Circa nell'ordine mi piacerebbe controllare loro:

  • Altri plugin: potrebbe che il comportamento causati da altri file ARX? Possono essere disabilitati su un sistema cattivo?
  • PerfMon: Controllare se si verificano errori di pagina soft/hard o errori di cache durante l'eliminazione (spero che sia possibile configurarlo sul computer dei clienti).
  • HeapQueryInformation: stessi valori in ambiente buono/cattivo?
  • Blocco Heap: Alcuni thread potrebbero essere altamente attivi in ​​background, tenendo stretto il blocco dell'heap? È possibile eseguire il test avvolgendo il ciclo in HeapLock/HeapUnlock (e ovviamente all'interno del blocco, ovviamente).
  • Ganci: È possibile agganciare il codice corrispondente? (ad esempio, un'app di terze parti che si collega alle funzioni di heap C++/Win32 per fare tutto ciò che vuole)
  • Afferrare a cannucce: La durata della rispettiva new è insolitamente lunga? Come vengono distribuiti i singoli delete volte?
1

Potrebbe essere dovuto a una diversa efficienza della cache tra il sistema funzionante/malfunzionante. Potrebbe esserci una maggiore frammentazione della memoria sul sistema in errore, che fa sì che l'eliminazione di grandi dimensioni possa danneggiare la cache. Su un sistema quiescente i dati potrebbero risultare più sequenziali e ottenere più hit nella cache durante l'eliminazione completa.

Provare il monitor contatore prestazioni Intel?

1

Se è accettabile e possibile, provare a utilizzare un profiler sul computer del cliente.

Si può provare AMD CodeAnalyst o il profiler Intel (anche se quello non è gratuito).

Se ciò non è possibile, aggiungere codice di profiling alle build di rilascio e raccogliere i risultati dal cliente. Anche un semplice codice di profilazione può aiutarti a trovare il vero collo di bottiglia.

Non sembra che l'eliminazione stessa sia il problema, ma il problema potrebbe essere un'altra parte del codice.

E.g. - qual è il tipo di head->resval.rstring?

0

Ci imbattiamo sempre in questo. Non c'è niente di sbagliato nel tuo codice, l'eliminazione di migliaia di elementi può richiedere diversi secondi (e l'ho visto anche raggiungere i minuti) anche in modalità di rilascio.

La risposta è quella di non eliminare. Prendi un vero allocatore di memoria e invece di allocare individualmente ogni oggetto crea un pool di memoria (o un heap personalizzato o qualsiasi altra cosa tu voglia chiamarlo). Nedmalloc è ciò che usiamo e raccomandiamo, e puoi creare un "nedpool". In sostanza, un pool è un blocco di memoria da cui verranno allocati gli oggetti. Si assegna ancora memoria per ogni oggetto, ma viene prelevato dal pool anziché direttamente dal sistema operativo.

Quando arriva il momento dell'eliminazione, è sufficiente eliminare l'intero pool anziché eliminare gli oggetti uno a uno. Utilizzare un pool diverso per ogni lotto di oggetti che scadrà allo stesso tempo. Non è necessario allocare la memoria per l'intero pool in anticipo, ma è possibile solo eliminare l'intera operazione in una sola volta.

+0

La maggior parte degli oggetti C++ ha un comportamento non definito se si esegue questa operazione. Hai almeno bisogno di organizzare i distruttori degli oggetti contenuti da chiamare. –

+0

Naturalmente. È necessario utilizzare il nuovo posto sul posto e quindi chiamare manualmente il distruttore, ma non rilasciare la memoria. –

0

Come viene generato il retlist? Inoltre, esiste un motivo per cui stai allocando ed eliminando manualmente i resbuf invece di utilizzare acutNewRb e acutRelRb?

Inoltre, probabilmente è stato controllato, ma l'utente ha il disegno predefinito caricato sia in AutoCAD 2009 che nel 2011? In caso contrario, i disegni sono uguali (ad eccezione della versione ACAD) e si trovano localmente o su un'unità di rete? Si potrebbe anche verificare se l'utente ha le stesse applicazioni lisp/.Net/objectARX in esecuzione in entrambe le istanze. Inoltre, AutoCAD 2011 è una rete o un'installazione locale?

Infine, è possibile aggiungere tag autocad e objectarx alla domanda.

+0

retList viene generato utilizzando acutBuildList. Stavo usando acutRelRb per rilasciare la memoria, ma mentre creavo il profilo del codice, ho trovato che la funzione fosse il problema. L'ho riscritto manualmente per vedere se ciò avrebbe risolto il problema (non lo era) e in modo da avere un'idea migliore di cosa stava causando il problema. In tutti i casi sto eseguendo il codice sullo stesso disegno. –

Problemi correlati