Javascript For循环太慢

Javascript For循环太慢,javascript,node.js,performance,for-loop,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", "|?", "®",

我有以下代码:

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个单词,并将它们从新行保存到output.txt中


如果生成的单词数量不太多,则此代码运行速度很快,但在我的示例中,将生成411642个单词,并且我使用output.txt中的\n从换行符中编写它们。我使用这段代码的速度大约是82字/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方法来实现这一点。

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

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


此外,在一个for循环的中间放置一个异步操作,这会使系统过载,因为它不可能启动并执行许多异步操作,同时它们将最终被系统排队。

欢迎来到组合数学的世界。您将生成一个指数级增长的结果集。Javascript并不是这方面最快的语言。@EricJ。那么,我可以在这里使用什么最简单、最快的方法来获取我的单词列表呢?如果你使用console.log运行循环,删除它,它会使它更快。不知道为什么会有这么多的反对票,这是一个写得很好的问题,并且很清楚OP想要什么…@dandavis this console.log console.logcp.toArray[index],不是appendFile Callback中的那个谢谢,但是我怎样才能只打开一次文件?如何使用缓冲I/O?@cebit933-嗯,在循环之前打开文件。在循环过程中将所有单词收集到一个数组中,然后在循环结束时将它们全部写出并关闭文件。这是文件I/O的基础知识。您还可以使用文件流,它将为您提供缓冲区。