最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do you add verbose logging code to functions without affecting performance? - Stack Overflow

programmeradmin0浏览0评论

Performance is important for a certain class I'm writing.

I thought about calling a function like so:

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

And the contents would be like

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

So I wonder: is this enough for V8 to flag this as "dead code" if the DEBUG variable never changes?

Edit: I'm more worried about the performance in Node than on the browser, so removing the code while minifying would be insufficient.

Edit2: I made a JSPerf benchmark out of the proposed solutions, and they are very surprising:

Performance is important for a certain class I'm writing.

I thought about calling a function like so:

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

And the contents would be like

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

So I wonder: is this enough for V8 to flag this as "dead code" if the DEBUG variable never changes?

Edit: I'm more worried about the performance in Node than on the browser, so removing the code while minifying would be insufficient.

Edit2: I made a JSPerf benchmark out of the proposed solutions, and they are very surprising: http://jsperf./verbose-debug-loggin-conditionals-functions-and-no-ops/3

Share Improve this question edited Sep 12, 2014 at 12:41 Jelle De Loecker asked Sep 12, 2014 at 9:16 Jelle De LoeckerJelle De Loecker 22k29 gold badges104 silver badges146 bronze badges 1
  • github./duongchienthang/js-logger – Believe2014 Commented Jan 29, 2015 at 15:30
Add a ment  | 

3 Answers 3

Reset to default 2

I use ments that when a file is minified get removed, such as:

function name(arg) {
    // <debug>
    if (!arg) {
        throw new Error("arg must be defined"); 
    }
    // </debug>
    ... code goes here
}

For example: https://github./PANmedia/raptor-editor/blob/master/src/raptor-widget.js#L29-L33

An my (custom) build script to do the aforementioned https://github./PANmedia/raptor-build/blob/master/build/raptor-builder.js#L305-L313

There's a couple of solutions available(aside Petah's...):

  1. Use UglifyJS2 conditional pilation:

You can use the --define (-d) switch in order to declare global variables that UglifyJS will assume to be constants (unless defined in scope). For example if you pass --define DEBUG=false then, coupled with dead code removal UglifyJS will discard the following from the output:

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

UglifyJS will warn about the condition being always false and about dropping unreachable code; for now there is no option to turn off only this specific warning, you can pass warnings=false to turn off all warnings.

Another way of doing that is to declare your globals as constants in a separate file and include it into the build. For example you can have a build/defines.js file with the following:

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

uglifyjs build/defines.js js/foo.js js/bar.js... -c UglifyJS will notice the constants and, since they cannot be altered, it will evaluate references to them to the value itself and drop unreachable code as usual. The possible downside of this approach is that the build will contain the const declarations.

  1. Use a wrapper function.

For example you have this method:

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

You add logging to it by wrapping it in a logger function:

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.plicatedMethod = logger(function (arg1, arg2, arg3) {
    stuff...
});

This way the only performance hit would be at startup time. You can also use AOP method with the above wrapper function:

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

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

And you can pass information to the logger by adding properties to the function:

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

You can have a look at this question where someone created code that creates a logger for functions in an object recursively. Also check this answer of mine.

  1. Use C Pre Processor.

You can just do something like this:

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

or something like this

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

Then you can do this in your code

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

Or you use it's npm warapper: laudanumscript

  1. Create a sweetjs macro.

I haven't been able to find conditional pilation with sweetjs, but I'm sure it wouldn't be too hard to implement it. The end syntax would be(or should be!) similar to cpp.

You can use a logger library that supports:

  1. Logging level
  2. Late binding functions

Example: https://github./duongchienthang/js-logger

发布评论

评论列表(0)

  1. 暂无评论