for循环太慢了
Posted
技术标签:
【中文标题】for循环太慢了【英文标题】:For loop is too slow 【发布时间】:2016-01-01 13:01:38 【问题描述】:我有以下代码:
var Combinatorics = require('js-combinatorics');
var fs = require('fs');
cp = Combinatorics.cartesianProduct(
["4", "@", "/\\", "/-\\", "^", "∂", "λ", "α", "(!", "Z", "α"], ["1²", "2", "?", "P\\", "[\"/_", "l\"/_", "|-", "|2", "|?", "®", "12", "/2", "I2", "|^", "|~", "(r)", "|`", "l2", "Я", "ʁ", "я"], ["#", "(-)", ")-(", "/-/", "4", "<~>", "[-]", "\\-\\", "]-[", "]~[", "-", "=", "|-|", "|~|", "", ":-:", "-", "н"], ["!", "'", "1", "[]", "][", "|", "¦", "¡", ":", "]", "ι"], ["&", "3", "€", "£", "ë", "[-", "|=-", "ə", "ε"]
);
for(var index = 0; index < cp.length; ++index)
//may be not the best idea, but in this way I will add new line to each word when saving them into array
var aux = cp.toArray()[index] + '\n';
console.log(cp.toArray()[index])
var contents = fs.appendFile("./output.txt", aux,
function(error)
if(error)
console.log("error writing");
);
它将生成411642个单词并将它们从新行“\n
”保存到output.txt中
如果我生成的单词数量不多,此代码运行速度很快,但在我的情况下,要生成 411642 个单词,我使用 output.txt 中的“\n
”从换行符编写它们。我使用此代码的速度约为 82 个字/1 分钟。它超级慢。我不明白为什么?我怎样才能让它更快?
【问题讨论】:
欢迎来到组合数学的世界。您生成了一个呈指数增长的结果集。 javascript 不是最快的语言。 @EricJ。那么我可以在这里使用什么最简单、最快速的方式来获取我的单词表)? 如果您正在使用 console.log 运行循环,请将其删除,它会使其更快。 不知道为什么会有这么多反对票,这是一个写得很好的问题,而且很清楚 OP 想要什么...... @dandavis this console.log console.log(cp.toArray()[index]) ,不是 appendFile 回调中的那个 【参考方案1】:你应该做一个字符串插值或创建一个数组,然后将值推送给它。
最后,您将追加整个字符串,或使用Array.prototype.join
将其转换为字符串。
for
循环很快,问题在于 I/O。看看下面的例子:
var Combinatorics = require('js-combinatorics');
var fs = require('fs');
var cp = Combinatorics.cartesianProduct(
["4", "@", "/\\", "/-\\", "^", "∂", "λ", "α", "(!", "Z", "α"],
["1²", "2", "?", "P\\", "[\"/_", "l\"/_", "|-", "|2", "|?", "®", "12", "/2", "I2", "|^", "|~", "(r)", "|`", "l2", "Я", "ʁ", "я"],
["#", "(-)", ")-(", "/-/", "4", "<~>", "[-]", "\\-\\", "]-[", "]~[", "-", "=", "|-|", "|~|", "", ":-:", "-", "н"],
["!", "'", "1", "[]", "][", "|", "¦", "¡", ":", "]", "ι"],
["&", "3", "€", "£", "ë", "[-", "|=-", "ə", "ε"]
);
fs.appendFile('./output.txt', cp.toArray().join('\n'), function(error)
if (error)
console.log('Error writing ' + error);
);
注意:我在这里做的另一件事是将cp.toArray()
缓存到一个变量中,因此您不需要在每次循环迭代时调用它一次。做这两件事(只写一次文件,也只调用一次.toArray()
,你会有更好的性能,完全确定。
更新
我刚刚意识到你根本不需要循环,因为你唯一要做的就是为你拥有的每个单词连接一个 \n
,你可以通过调用 Array.prototype.join
方法来做到这一点.
【讨论】:
【参考方案2】:在任何使用文件 I/O 的循环中,您首先要检查的是如何最小化文件操作,因为这通常比 CPU 任务慢几个数量级。
这段代码只是在很多方面设计错误。对于初学者,不要将每个单词一次一个单词写入文件,并为每个单词调用fs.appendFile()
。打开文件一次。然后使用缓冲 I/O(如流)进行写入,这样您就不会为每个单词都打开、写入、关闭文件。或者,将所有单词收集到一个数组中,然后一次全部写入。
另外,您在 for
循环的中间放置了一个异步操作,这将使您的系统过载,因为它不可能同时启动和执行那么多异步操作(它们最终会得到由系统排队)。
【讨论】:
谢谢,但是我怎样才能只打开一次文件呢?以及如何使用缓冲 I/O? @cebit933 - 呃,在循环之前打开文件。在循环期间将所有单词收集到一个数组中,然后在循环结束时将它们全部写出并关闭文件。这是文件 I/O 基础知识。您还可以使用将为您缓冲的文件流。以上是关于for循环太慢了的主要内容,如果未能解决你的问题,请参考以下文章