2011-02-03 6 views
8

Ho scritto una classe di log e una funzione come nel codice seguente:Prestazioni MethodBase.GetCurrentMethod()?

Log(System.Reflection.MethodBase methodBase, string message) 

Ogni volta che accedo qualcosa che anche registrare il nome della classe dal methodBase.Name e methodBase.DeclaringType.Name.

Ho letto il seguente post Using Get CurrentMethod e ho notato che questo metodo è lento.

Devo usare il this.GetType() invece di System.Reflection.MethodBase o dovrei registrare manualmente il nome della classe/metodo nel mio log, ad es. Log ("ClassName.MethodName", "messaggio di log)? Qual è la migliore pratica?

+0

@loannis, viene posta una domanda simile qui. Controlla il link http://stackoverflow.com/questions/1466740/using-getcurrentmethod-in-supposedly-high-performance-code – RameshVel

+0

Da daniels answer "this.GetType() richiesto 2,5 ns per chiamata mentre MethodBase.GetCurrentMethod() .DeclaringType richiesto 2490 ns per chiamata - quindi hai una velocità del fattore 1200 circa. " – RameshVel

+0

@Ramesh: hai notato che erano esattamente le stesse domande a cui si era già collegato nella domanda? –

risposta

9

Dipende.

Se si utilizza l'approccio this.GetType() si perderanno le informazioni metodo, ma si avrà un grande guadagno di prestazioni (apparentemente un fattore di 1200, in base al collegamento)

Se offri un'interfaccia che consente al chiamante di fornire stringhe (ad esempio Log("ClassName.MethodName", "log message"), probabilmente otterrai prestazioni ancora migliori, ma ciò rende la tua API meno amichevole (lo sviluppatore chiamante deve fornire il nome della classe e il nome del metodo)

2

So che questa è una vecchia questione, ma ho pensato di buttare fuori una soluzione semplice che sembra funzionare bene e mantiene simboli

static void Main(string[] args) 
    { 
     int loopCount = 1000000; // 1,000,000 (one million) iterations 
     var timer = new Timer(); 

     timer.Restart(); 
     for (int i = 0; i < loopCount; i++) 
      Log(MethodBase.GetCurrentMethod(), "whee"); 
     TimeSpan reflectionRunTime = timer.CalculateTime(); 

     timer.Restart(); 
     for (int i = 0; i < loopCount; i++) 
      Log((Action<string[]>)Main, "whee"); 
     TimeSpan lookupRunTime = timer.CalculateTime(); 

     Console.WriteLine("Reflection Time: {0}ms", reflectionRunTime.TotalMilliseconds); 
     Console.WriteLine(" Lookup Time: {0}ms", lookupRunTime.TotalMilliseconds); 
     Console.WriteLine(); 
     Console.WriteLine("Press Enter to exit"); 
     Console.ReadLine(); 

    } 

    public static void Log(Delegate info, string message) 
    { 
     // do stuff 
    } 

    public static void Log(MethodBase info, string message) 
    { 
     // do stuff 
    } 

    public class Timer 
    { 
     private DateTime _startTime; 

     public void Restart() 
     { 
      _startTime = DateTime.Now; 
     } 

     public TimeSpan CalculateTime() 
     { 
      return DateTime.Now.Subtract(_startTime); 
     } 
    } 

L'esecuzione di questo codice mi dà i seguenti risultati:

Reflection Time: 1692.1692ms 
    Lookup Time: 19.0019ms 

Press Enter to exit 

Per un milione di iterazioni, questo non è male per tutto, in particolare rispetto alla riflessione verticale. Il gruppo di metodi viene trasmesso a un tipo Delegato, si mantiene un collegamento simbolico fino in fondo nella registrazione. Non ci sono buffe stringhe magiche.

+1

Se stai basando i tuoi calcoli sul codice esatto che hai postato, senza che nulla accada effettivamente nei metodi Log stessi, non ti aspetti che il percorso del delegato impieghi meno tempo, perché in realtà non è possibile fare nulla? Sei effettivamente in grado di ottenere il nome del metodo che stai passando al metodo 'Log (Delegate info ...'? ' – Zack

+1

Come previsto da @Zack, l'accesso alla proprietà Name nei metodi Log fa la differenza: li ho modificati per restituire rispettivamente 'MethodBase.Name' e' Delegate.Method.Name'. I miei risultati sono diventati 'Tempo di riflessione: 1178,6813ms Tempo di ricerca: 482,2953ms'. Ancora, la" Ricerca "- l'approccio porta a un'esecuzione più rapida. –