2014-09-12 33 views
7

Le prestazioni sono importanti per una certa classe che sto scrivendo.Come si aggiunge codice di registrazione dettagliato alle funzioni senza influire sulle prestazioni?

ho pensato di chiamare una funzione in questo modo:

debug('This is a debug message, only visible when debugging is on'); 

E il contenuto sarebbe come

function debug(message) { 
    if (DEBUG) console.log(message); 
} 

Allora mi chiedo: è questo sufficiente per V8 per segnalare questo come "codice morto" se la variabile DEBUG non cambia mai?

Modifica: Sono più preoccupato per le prestazioni in Nodo che sul browser, quindi rimuovere il codice mentre il minimo sarebbe insufficiente.

Edit2: Ho fatto un punto di riferimento JSPerf fuori delle soluzioni proposte, e sono molto sorprendente: http://jsperf.com/verbose-debug-loggin-conditionals-functions-and-no-ops/3

+0

https://github.com/duongchienthang/js -logger – Believe2014

risposta

1

Ci sono un paio di soluzioni disponibili (a parte Petah's ...):

  1. Uso UglifyJS2 conditional compilation:

È possibile utilizzare la --define (-d) Interruttore in ordine per dichiarare le variabili globali che UglifyJS assumerà come costanti (a meno che non siano definite nell'ambito ). Ad esempio se si passa --define DEBUG = falso allora, insieme con il codice morti UglifyJS rimozione scarterà il seguente dalla uscita:

if (DEBUG) { 
    console.log("debug stuff"); 
} 

UglifyJS avvertirà sulla condizione essendo sempre falsa e circa cadere irraggiungibile codice; per ora non vi è alcuna opzione per disattivare solo questo avviso specifico, è possibile passare warnings = false per disattivare tutti gli avvisi .

Un altro modo per farlo è dichiarare i globali come costanti in un file separato e includerlo nella compilazione. Per esempio si può avere un file build/defines.js con il seguente:

const DEBUG = false; 
const PRODUCTION = true; 
// etc. 
and build your code like this: 

uglifyjs costruire/defines.js js/foo.js js/bar.js ... -c UglifyJS volontà avviso le costanti e, dal momento che non possono essere alterate, sarà valutare i riferimenti ad esse al valore stesso e rilasciare il codice irraggiungibile come al solito. L'eventuale svantaggio di questo approccio è che la build conterrà le dichiarazioni const.

  1. Utilizzare una funzione wrapper.

Per esempio si dispone di questo metodo:

exports.complicatedMethod = function (arg1, arg2, arg3) { 
    stuff... 
}; 

si aggiunge la registrazione ad esso avvolgendolo in una funzione logger:

function logger(fn) { 
    if (!DEBUG) { 
     return fn; 
    } 
    return function() { 
     console.log(fn.name, arguments); // You can also use `fn.toString()` to get the argument names. 
     fn.apply(this, arguments); 
    }; 
} 

exports.complicatedMethod = logger(function (arg1, arg2, arg3) { 
    stuff... 
}); 

In questo modo l'unico calo di prestazioni sarebbe in fase di avvio tempo. È inoltre possibile utilizzare AOP metodo con l'funzione wrapper sopra:

exports.complicatedMethod = function (arg1, arg2, arg3) { 
    stuff... 
}; 

if (DEBUG) { 
    for (var name in exports) { 
     exports[name] = logger(exports[name]); 
    } 
} 

E si può passare informazioni al logger aggiungendo le proprietà alla funzione:

exports.complicatedMethod.description = 'This function only shows how tired i was when I was writing it and nothing else!'; 

si può avere uno sguardo a this question dove qualcuno codice creato che crea un logger per le funzioni in un oggetto in modo ricorsivo. Controlla anche this answer of mine.

  1. Utilizzare C Pre Processor.

si può semplicemente fare qualcosa di simile:

#if DEBUG 
    console.log("trace message"); 
#endif 

o qualcosa di simile

#if DEBUG 
#define DEBUG_LOG(x) console.log(x); 
#else 
#define DEBUG_LOG(x) //console.log(x); 
#endif 

Poi si può fare questo nel codice

DEBUG_LOG('put a random message her to confuse sys admins!') 

O si utilizza è npm warapper: laudanumscript

  1. Creare un sweetjs macro.

Non sono stato in grado di trovare la compilazione condizionale con sweetjs, ma sono sicuro che non sarebbe troppo difficile implementarlo. La sintassi di fine sarebbe (o dovrebbe essere!) Simile a cpp.

+0

Ho dimenticato di dire che era per lo più per Node.js (sono meno preoccupato per i millisecondi sul browser), quindi non è ideale ripararlo con il minify. Ho fatto [fare un benchmark JSPerf] (http://jsperf.com/verbose-debug-loggin-conditionals-functions-and-no-ops/2) per provare le tue soluzioni proposte, e sono sorprendenti! I no-op sembrano fare abbastanza male, tranne su Firefox. – skerit

+0

In realtà guardando il tuo benchmark ho la sensazione che dal momento che non ci sia un vero codice, le ottimizzazioni JIT potrebbero rimuovere il tutto come un codice morto ...Potresti voler provare qualcosa con effetti collaterali, in modo che non venga rimosso come codice morto. –

+0

Sì, ma questo è lo scopo dei messaggi di debug no-op. SpiderMonkey sembra gestirli come ci si aspetterebbe: sono i più veloci. – skerit