2012-05-05 9 views
5

Ho scritto l'operatore personalizzato new e l'operatore delete per la classe MyOrder. Sto allocando memoria usando boost :: singleton pool. Ecco il programma di verifica delle prestazioni,Assegnazione personalizzata utilizzando boost singleton_pool più lento del valore predefinito

#include <boost/pool/singleton_pool.hpp> 
#include <boost/progress.hpp> 
#include <iostream> 
#include <new> 
#include <vector> 


class MyOrder{ 
    std::vector<int> v1_; 
    std::vector<double> v2_; 

    std::string s1_; 
    std::string s2_; 

public: 
    MyOrder(std::string s1, std::string s2): s1_(s1), s2_(s2) {} 

    ~MyOrder(){} 

    static void * operator new(size_t size); 
    static void operator delete(void * rawMemory) throw(); 
}; 

struct MyOrderTag{}; 
typedef boost::singleton_pool<MyOrderTag, sizeof(MyOrder)> MyOrderPool; 

void* MyOrder:: operator new(size_t size) 
{ 
    if (size != sizeof(MyOrder)) 
     return ::operator new(size); 

    while(true){ 
     void * ptr = MyOrderPool::malloc(); 
     if (ptr != NULL) return ptr; 

     std::new_handler globalNewHandler = std::set_new_handler(0); 
     std::set_new_handler(globalNewHandler); 

     if(globalNewHandler) globalNewHandler(); 
     else throw std::bad_alloc(); 

    } 
} 

void MyOrder::operator delete(void * rawMemory) throw() 
{ 
    if(rawMemory == 0) return; 
    MyOrderPool::free(rawMemory); 
} 

int main() 
{ 
    MyOrder* mo = NULL; 
    std::vector<MyOrder*> v; 
    v.reserve(100000); 

    boost::progress_timer howlong; 
    for(int i = 0; i< 100000; ++i) 
    { 
     mo = new MyOrder("Sanket", "Sharma"); 
     v.push_back(mo); 
    } 

    for (std::vector<MyOrder*>::const_iterator it = v.begin(); it != v.end(); ++it) 
    { 
     delete *it; 
    } 
    return 0; 
} 

ho compilato il programma di cui sopra con -O2 bandiera e corse sul mio MacBook con 2,26 GHz Intel Core 2 Duo e ci sono voluti 0,16 secondi. Quindi ho commentato le righe in cui ho dichiarato e definito l'operatore personalizzato nuovo e l'eliminazione dell'operatore, ricompilato con i flag -O2 e eseguito sulla stessa macchina impiegando 0,13 secondi.

L'allocazione e la deallocazione della memoria utilizzando singleton_pool per oggetti della stessa dimensione dovrebbero accelerarla. Perché è lento? Oppure il sovraccarico di creare una piscina annullerebbe il vantaggio prestazionale ottenuto in questo piccolo programma?

Aggiornamento:

ho sostituito le due variabili std :: string con un int e un doppio e questa volta correva i due programmi con 100.000.000 (cioè 1000 volte prima) iterazioni ciascuno su un 3.0 GHZ AMD Phenom (tm) II processore X4 945. Quella che utilizza l'allocazione della memoria personalizzata impiega 3,2 secondi mentre quella che utilizza l'allocazione di memoria predefinita impiega 8,26 secondi. Quindi questa volta l'allocazione della memoria personalizzata vince.

+1

Dal momento che si sta prendendo la briga di chiamare * uno * nuovo gestore, probabilmente si dovrebbe scrivere un ciclo per provare * tutti * nuovi gestori. –

+1

Il tuo test include le allocazioni di 'std :: string' che non sono governate dall'allocatore personalizzato, quindi qualsiasi risultato ottenuto è fuorviante _at best_. – Chad

+0

@Chad I ha sostituito std :: string con un double e un int. Questa volta li sto iterando 10000000 volte. I risultati sono 1,95 per default vs 2,29 per personalizzato. L'allocazione/deallocazione fissa tramite pool è più lenta. – sank

risposta

5

Penso che i tuoi numeri non abbiano significato. Se hai verificato il runtime solo una volta e hai trovato 0.13 rispetto a 0.16 secondi rispetto a quello che è completamente privo di significato e dominato da sovraccarico.

È necessario eseguire lo snippet che si desidera testare migliaia di volte e quindi confrontare i dati per escludere il sovraccarico.

No davvero, che differenza 0.03 secondi può essere facilmente spiegato con il processo ottenendo commutata, ecc