如何在不影响性能的情况下将详细日志logging代码添加到函数中?
对于我正在编写的某个课程,performance很重要。
我想过调用一个这样的函数:
debug('This is a debug message, only visible when debugging is on');
内容会是这样的
function debug(message) { if (DEBUG) console.log(message); }
所以我想知道:如果DEBUG
variables永远不会改变,V8是否足以将其标记为“死代码”?
编辑:我更担心节点比在浏览器的性能,所以在缩小的时候删除代码是不够的。
编辑2:我提出了一个JSPerf基准testing的解决scheme,他们是非常令人惊讶的: http : //jsperf.com/verbose-debug-loggin-conditionals-functions-and-no-ops/3
有几个解决scheme可用(旁边的Petah的 …):
- 使用UglifyJS2条件编译 :
您可以使用–define(-d)开关来声明UglifyJS将假定为常量的全局variables(除非在作用域中定义)。 例如,如果你传递–define DEBUG = false,那么再加上死代码的移除,UglifyJS会从输出中丢弃以下内容:
if (DEBUG) { console.log("debug stuff"); }
UglifyJS会警告总是出现错误的情况,并会丢弃无法访问的代码; 现在没有选项只能closures这个特定的警告,你可以通过warnings = false来closures所有的警告。
另一种方法是将你的全局variables声明为一个单独的文件,并将其包含到构build中。 例如你可以使用下面的build / defines.js文件:
const DEBUG = false; const PRODUCTION = true; // etc. and build your code like this:
uglifyjs build /developers.js js / foo.js js / bar.js … -c UglifyJS会注意到这些常量,因为它们不能被修改,所以它会评估对它们的引用,并像往常一样放弃无法访问的代码。 这种方法可能的缺点是构build将包含常量声明。
- 使用包装函数。
比如你有这个方法:
exports.complicatedMethod = function (arg1, arg2, arg3) { stuff... };
通过将logging包装到logging器函数中来添加logging:
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... });
这种方式唯一的performance将是在启动时间。 你也可以使用上面的包装函数使用AOP方法:
exports.complicatedMethod = function (arg1, arg2, arg3) { stuff... }; if (DEBUG) { for (var name in exports) { exports[name] = logger(exports[name]); } }
你可以通过给函数添加属性来传递信息给logging器:
exports.complicatedMethod.description = 'This function only shows how tired i was when I was writing it and nothing else!';
你可以看看这个问题 ,其中有人创build了代码,recursion地为对象中的函数创build一个logging器。 也检查我的这个答案 。
- 使用C预处理器 。
你可以做这样的事情:
#if DEBUG console.log("trace message"); #endif
或者类似的东西
#if DEBUG #define DEBUG_LOG(x) console.log(x); #else #define DEBUG_LOG(x) //console.log(x); #endif
那么你可以在你的代码中做到这一点
DEBUG_LOG('put a random message her to confuse sys admins!')
或者你用它的npm warapper:laudanumscript
- 创build一个sweetjsmacros 。
我还没有findsweetjs的条件编译,但我相信它不会太难实现它。 最后的语法应该是(或应该是!)类似于CPP。
我使用的评论,当一个文件被缩小被删除,如:
function name(arg) { // <debug> if (!arg) { throw new Error("arg must be defined"); } // </debug> ... code goes here }
例如: https : //github.com/PANmedia/raptor-editor/blob/master/src/raptor-widget.js#L29-L33
我的(自定义)生成脚本做上述https://github.com/PANmedia/raptor-build/blob/master/build/raptor-builder.js#L305-L313
您可以使用支持以下function的logging器库:
- logging级别
- 后期绑定function
例如: https : //github.com/duongchienthang/js-logger