Domanda

Attualmente sto lavorando su software di rete.Ha una classe principale, server che ovviamente rappresenta un'istanza del server.

Un'istanza server può inviare richieste e l'utente è informato della risposta da parte di un callback.

Il codice è come:

class server
{
  public:
    typedef boost::function<void (int duration)> callback_func;

    void send_request(endpoint& ep, callback_func cb);
};
.

Ora diciamo che, come utente che voglio il callback per sapere sull'istanza che lo ha chiamato, posso fare la seguente cosa:

void mycallback(const server& sv, int duration) { ... }

server sv;
sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1));
.

Ma mi chiedo: c'è un overhead lo fa?Le chiamate a mycallback saranno più lenti rispetto all'utilizzo di una chiamata "normale"?

Grazie.

Foot Nota: Potrei ovviamente cambiare il mio typedef a: typedef boost::function<void (const server& sv, int duration)> callback_func; e se boost::bind causi un sovraccarico significativo, questo è probabilmente quello che farò alla fine.Vorrei solo sapere quali costi implica l'uso di boost::bind.

È stato utile?

Soluzione

Ovviamente causa un sovraccarico.Quello che fa è che crea un funtore che memorizza i parametri associati e ha un operator() che chiami con gli argomenti rimanenti.Ora, è significativo?Non lo so, perché è solo una parola.Fai 10 milioni di richieste e misurale.Sei l'unico che può dire se questo overhead è significativo per te o no.

Inoltre, ho riscontrato un problema simile.Dato che non avevo davvero bisogno di delegati, potevo farla franca con i puntatori a funzione.Ma ho trovato un interessante benchmark che menziona anche alcune implementazioni alternative, tutte conprestazioni migliori rispetto a boost::function.Ciò va a scapito della portabilità e in alcuni casi di brutti hack non standard nell'implementazione (ma in cambio di una prestazione davvero buona).

Altri suggerimenti

boost::bind genera un oggetto funzionale che può essere ottimizzato se utilizzato come argomento per i modelli di funzione, ma boost::function impedisce questa ottimizzazione, proprio come il passaggio di un puntatore a una funzione ne impedisce l'inlining.boost::function stesso non deve introdurre più overhead di una funzione virtuale all o chiamare tramite un puntatore alla funzione.

PS.Sono d'accordo con Tamás Szelei: fai 10 milioni di richieste e misurale.

Rispetto a una normale chiamata di funzione, stai pagando due indirette per la chiamata di funzione, che è simile al sovraccarico di una chiamata di funzione virtuale (non devirtualizzata).

Il primo indiretto è dovuto alla cancellazione del tipo che avviene in boost :: function (questo è documentato nella documentazione boost::function).Questo non può essere ottimizzato e avresti la stessa penalità anche con un puntatore a funzione nudo.

Il secondo riferimento indiretto deriva dalla chiamata alla funzione mycallback tramite un puntatore a funzione.Un compilatore molto ben ottimizzato può capirlo e ottimizzarlo, ma un normale compilatore no.Puoi sbarazzarti di questo riferimento indiretto (in tutti i compilatori) se trasformi mycallback in un oggetto funzione:

Invece di

void mycallback( .1. ) { .2. }

lo fai

struct mycallback {
    void operator()( .1. ) const { .2. }
};

Tieni presente che boost :: bind causa una copia del funtore.Questo può essere molto significativo.Per il mio sistema operativo le notizie e le cancellazioni sono molto costose.Vedere la documentazione boost :: bind su ref () e cref ().Credo che le funzioni membro causino anche copie del funtore, ma non c'è documentazione al riguardo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top