2016-02-12 9 views
5

Esiste un modo più efficiente di fare quanto segue, qualcosa ci sembra semplicemente sbagliato? Sto cercando il modo più efficiente di logging logaritmico.Registrazione logaritmica 1, 10, 100, 1000, ecc.

public bool Read() 
    { 
     long count = Interlocked.Increment(ref _count); 
     switch (count) 
     { 
      case 1L: 
      case 10L: 
      case 100L: 
      case 1000L: 
      case 10000L: 
      case 100000L: 
      case 1000000L: 
      case 10000000L: 
      case 100000000L: 
      case 1000000000L: 
      case 10000000000L: 
      case 100000000000L: 
      case 1000000000000L: 
      case 10000000000000L: 
      case 100000000000000L: 
      case 10000000000000000L: 
      case 100000000000000000L: 
      case 1000000000000000000L: 
       _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read"); 
       break; 
     } 

     return _reader.Read(); 
    } 

Aggiornamento:

Qui sono i miei test di benchmark micro.

  • Method1: il modo di Übercoder con tenere il passo con lo stato
  • Method2: Il mio modo con il grande istruzione switch
  • method3: modo di Markus Weninger con la bella funzione matematica

Dal momento che per me 100.000.000 i record letti senza registrazione impiegano circa 20 minuti, mentre altri 4 secondi non sono nulla. Vado con il bellissimo modo di fare la matematica. Mathod3 vince nel mio scenario.

Run time for 100,000,000 iterations averaged over 100 attempts 

Method1 Max: 00:00:00.3253789 
Method1 Min: 00:00:00.2261253 
Method1 Avg: 00:00:00.2417223 

Method2 Max: 00:00:00.5295368 
Method2 Min: 00:00:00.3618406 
Method2 Avg: 00:00:00.3904475 

Method3 Max: 00:00:04.0637217 
Method3 Min: 00:00:03.2023237 
Method3 Avg: 00:00:03.3979303 
+0

@Dai che si trova sul punto mobile, che non è il caso qui. Anche la domanda riguarda C#, non C++. Se ne hai una migliore, duplicati, fammi sapere. –

+1

L'uso di un'istruzione 'switch' come se fosse davvero il modo più veloce per farlo, poiché verrà compilato in una serie di istruzioni di hashtable a livello di processore che sono velocissime. Mentre il codice è "brutto" (beh, penso che sia un po 'bello) penso che si possa migliorare spostandolo in una funzione separata ('IsExactlyPowerOf10 (Int64 n)") e chiamandolo dalla funzione 'Leggi'. – Dai

+0

Grazie per il bel benchmark di tutti e tre i metodi :) –

risposta

8

Se le prestazioni non è un grosso problema, vorrei utilizzare i seguenti

if(Math.Log10(count) % 1 == 0) 
    _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read"); 

This question afferma quanto segue:

Per i numeri in virgola mobile, n% 1 == 0 è tipicamente il modo per verificare se c'è qualcosa oltre il punto decimale.


Modifica: Per completare la mia risposta, è anche possibile tenere traccia del successivo valore di registrazione, come @ Übercoder pubblicato nella sua risposta.

long nextLoggingValueForLogX = 1; 
if (count == nextLoggingValueForLogX) 
{ 
    nextLoggingValueForLogX *= 10; // Increase it by your needs, e.g., logarithmically by multiplying with 10 
    _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read"); 
} 

Tuttavia, questo metodo genererà una nuova variabile per ogni registro che non dovrebbe essere eseguita ogni volta. Questo introdurrà un codice extra e anche un lavoro extra se deve essere reso thread-safe.

+0

Farò un test delle prestazioni del mio contro il tuo e vedrò cosa esce più veloce, spero davvero che sia tuo perché è molto più bello. Anche se è un po 'più lento lo farò Probabilmente lo userò ancora Lasciami fare alcuni test di performance per vedere se posso segnare questo come risposta –

+0

Sì, sono anche interessato a questo Spero che funzioni per te –

3
static long logTrigger = 1; 


if (count == logTrigger) 
{ 
    logTrigger *= 10; 
    // do your logging 
} 
+0

Scommetto che il tuo è il più veloce, io Lo farò sapere: rimuoverei la statica dal trigger –

+0

Sì, questo sarà sicuramente il più veloce, ma, d'altra parte, introduce una nuova variabile per ogni log che dovrebbe essere eseguita logaritmicamente. scelta uno deve fare. –

+2

Sì, devo fare molto per rendere questo thread sicuro, dal momento che non lo è. –

Problemi correlati