因为循环太慢了

时间:2015-10-04 22:21:22

标签: javascript node.js performance for-loop

我有以下代码:

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分钟。这超级慢。我不明白为什么?我怎样才能快速完成?

2 个答案:

答案 0 :(得分: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方法。

答案 1 :(得分:0)

在任何使用文件I / O的循环中,您要检查的第一件事就是如何最小化文件操作,因为这通常比CPU任务慢几个数量级。

这段代码设计错误的方法很多。对于初学者来说,不要将每个单词一次写入一个单词,每个单词都需要fs.appendFile()。打开文件一次。然后使用缓冲的I / O(如流)进行写入,这样就不会对每个单词的文件进行打开,写入和关闭。或者,将所有单词收集到一个数组中,然后立即将它们全部写入。

另外,你在一个for循环的中间放置一个异步操作,这会使系统过载,因为它无法启动并同时执行那么多异步操作(它们将结束)排队等候系统。)