Gestire la registrazione facoltativa nella libreria ad alte prestazioni

7

Sto scrivendo una libreria in C ++ che deve essere veloce quanto ragionevolmente possibile. Tuttavia, mi piacerebbe anche essere in grado di fornire l'accesso nel caso in cui un utente (o me) ha bisogno di eseguire il debug dei possibili problemi.

Questa libreria deve essere compilata, ma contiene anche alcune classi basate sull'intestazione.

Come capisco, solitamente l'accesso alle librerie viene effettuato dichiarando, ma non definendo, una funzione di registrazione specifica, che viene utilizzata per registrare i messaggi all'interno della libreria. Questa funzione viene quindi definita all'interno del programma dell'utente, che registra con il meccanismo che l'utente desidera (o non registra affatto).

Dato che alcuni registri si trovano in posti molto sensibili alle prestazioni, mi chiedo se dovrei preoccuparmi che questo approccio possa avere un impatto sulle prestazioni della libreria anche quando l'utente non desidera affatto la registrazione. La libreria è solitamente collegata staticamente.

Un'idea alternativa che avrei avuto sarebbe quella di definire la registrazione come una macro e definirla sia durante la fase di creazione della libreria che durante la fase di costruzione del programma finale come una macro vuota o la funzione di generazione desiderata. Ciò garantirebbe che in caso di mancata registrazione, nulla resterebbe nel programma finale. Tuttavia, sarebbe più complicato per l'utente e probabilmente più complicato in quanto sarebbe necessario modificare un file di intestazione della libreria prima di creare la libreria per definire correttamente la macro.

Quali sono le migliori pratiche per questo tipo di problema?

    
posta Svalorzen 28.01.2018 - 13:28
fonte

1 risposta

4

Quando si tratta di prestazioni, c'è solo una best practice: measure ! Non indovinare su come si comportano le prestazioni, quelle che si sbagliano molto spesso.

Per il caso specificato, è possibile trovare la parte più critica delle prestazioni della propria libreria, misurarne le prestazioni quando si chiama una funzione di registrazione "vuota" (magari tramite un puntatore a funzione), quindi rimuovere la chiamata di funzione e misurare nuovamente. Se quel veramente si presenta come risultato di una notevole differenza di prestazioni, il passo successivo è pensare alle ottimizzazioni.

Ad esempio, la "funzione di registrazione" dovrebbe essere normalmente implementata come una classe astratta. Invece di fornire solo una funzione di registrazione vuota nel caso in cui la registrazione sia disabilitata, il logger potrebbe anche fornire una funzione booleana pubblica che consente un test se la registrazione è abilitata, quindi puoi utilizzarla per ottimizzarla in questo modo:

   class MyLibraryClass
   {
      AbstractLogger *logger;

      void myLibraryFunction()
      {
          double x = doSomeQuickCalculation();
          // relies on "log" to do nothing when logging is disabled
          loggger->log("doSomeQuickCalculation result=" + formatDouble(x));
      }

      void myLibraryFunction_Optimized()
      {
          double x = doSomeQuickCalculation();

          // optimization: avoid string formatting for logging if not required, 
          // (in case the string formatting is really the bottleneck)
          if(loggger->isLoggingEnabled())
          {
              loggger->log("doSomeQuickCalculation result=" + formatDouble(x));
          } 
      }
  }

Solo se viene visualizzato - per measurement - che questo è ancora troppo lento, è tempo di pensare a una soluzione in fase di compilazione, che può utilizzare macro o modelli.

Si noti che le soluzioni in fase di compilazione rendono più difficile attivare e disattivare la registrazione in fase di esecuzione. Nel caso in cui questo non sia un problema, il modo standard nel moderno C ++ è probabilmente quello di rendere il Logger un parametro template delle classi che necessitano di logging, con un Logger vuoto come default, e affidarsi all'ottimizzatore che eliminerà tutto chiama per svuotare le funzioni.

    
risposta data 28.01.2018 - 17:02
fonte

Leggi altre domande sui tag