如何在Javascript中避免调试代码降低运行时性能
我有一些对时间敏感的异步代码,只能通过记录实时数据然后查看日志来调试。因此,我用如下语句插入代码:如何在Javascript中避免调试代码降低运行时性能,javascript,debugging,preprocessor,Javascript,Debugging,Preprocessor,我有一些对时间敏感的异步代码,只能通过记录实时数据然后查看日志来调试。因此,我用如下语句插入代码: DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`); let debugOn = process.env["DEBUG_RATE_LIMIT_MAP"] === "1"; let DBG; if (debugOn) { DBG = function(...args) { args.un
DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`);
let debugOn = process.env["DEBUG_RATE_LIMIT_MAP"] === "1";
let DBG;
if (debugOn) {
DBG = function(...args) {
args.unshift(time() + ": ");
console.log(...args);
}
} else {
DBG = function() {};
}
其中DBG有如下实现:
DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`);
let debugOn = process.env["DEBUG_RATE_LIMIT_MAP"] === "1";
let DBG;
if (debugOn) {
DBG = function(...args) {
args.unshift(time() + ": ");
console.log(...args);
}
} else {
DBG = function() {};
}
一般的想法是,如果设置了环境变量,它只输出到控制台
这一切都很好,但让我感到困扰的是,即使在未设置环境变量时它不会输出到控制台,它仍然会计算所有调试语句的参数,例如:
DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`);
因此,它仍然在对每个语句进行一次性工作,以评估模板字符串。显然,JavaScript不是一种预处理语言,比如C++,可以编译调试代码。Javascript中有哪些技术可以在将来需要调试时将调试代码留在代码库中,但在不使用调试时不会降低运行时性能
对于任何其他代码参考,整个模块都在这里:。是否需要DBG始终作为一个函数?如果没有,您可以执行以下操作:
let debugOn = process.env["DEBUG_RATE_LIMIT_MAP"] === "1";
let DBG;
if (debugOn) {
DBG = function(...args) {
args.unshift(time() + ": ");
console.log(...args);
}
}
然后在代码中,检查DBG是否是函数,而不是直接调用DBG:
if (typeof DBG === "function") {
DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`);
}
这样,您确实会有if条件检查的开销,但可以避免在生产环境中执行字符串文字。根据一些评论,我目前的最佳想法是:
// environment variable that turns debug tracing on
let debugOn = process.env["DEBUG_RATE_MAP"] === "1";
function DBG(...args) {
if (debugOn) {
args.unshift(time() + ": ");
console.log(...args);
}
}
然后,在执行此操作的代码中:
if (debugOn) DBG(`Setting ${name} timer for ${amount} ms from runMore(${reason})`);
而且,如果它只是一个简单的字符串文字,因此不需要避免模板计算,我可以这样做:
DBG('All done.');
如果您使用任何类型的构建链,JS与任何预处理语言一样好——它只是编译成不同的JS。有transpiler插件可以从代码中删除调试语句。@Bergi-当前未使用生成链。另外,不要真的想删除代码,因为这样你就必须得到一个调试版本才能进行调试。所以,也许我的C++类比是一个坏的,因为这不是我真正想要的。我希望有一些运行时方案,实时成本更低。啊,好的。为此,我唯一能想到的就是使用带标记的模板文本,这样可以避免字符串连接。虽然不能确定它的开销,但您需要对其进行基准测试。@Bergi-我从来没有真正了解标记文字的常用用法。也许这是一种可能性,尽管在调用标记函数之前仍然解析模板文本,但它还没有生成完整的输出。是的,这会阻止额外的模板求值,但是在代码中到处散布是一种痛苦。我希望有更干净的东西。在这个特定的例子中,我可以使用if-debugOn…如果你使用typescript,你可以使用DBG?.stringLiteral,这样会更干净。最新的ES也会有:DBG会吗?如果DBG没有定义,templateLiteral会避免评估templateLiteral吗?这听起来可能很有趣,应该是。正如doc提到的,它将在DBG本身短路。它相当于DBG&&DBGtemplateLiteralIt很好,但是if条件在可读性方面更好,除非您将返回值赋给某个变量。另一件事:将其设为const debugOn=…。这样,优化编译器就可以推断假值不会改变,并且可以完全删除if块。@Bergi-我有意识地选择使用let,以便在调试时根据需要以编程方式更改该值。不过,了解优化是件好事。