简体   繁体   English

为什么字符串加载速度比数字加载速度慢得多?

[英]Why do strings load so much slower than numbers?

I wrote a script with the purpose of sequencing the Fibonacci Sequence (or any two numbers that would add to make the next, and then those two, etc.). 我写了一个脚本,目的是对斐波那契序列进行排序(或要添加为下一个的任何两个数字,然后再加上这两个数字,等等)。 When you press a button, the function (called fibonacci) adds the two values together, pushes the new value into an array (called sequence), and then displays the most recent value in the array. 当您按下按钮时,该函数(称为fibonacci)将两个值加在一起,将新值推入数组(称为sequence),然后显示数组中的最新值。 I set it up with a setInterval (called recursion), so it continues to add more values to the array, and display more numbers. 我使用setInterval (称为递归)对其进行设置,因此它将继续向该数组添加更多值,并显示更多数字。 I was experimenting with the function, and thought to try two strings instead of two numbers. 我正在对该函数进行实验,并考虑尝试使用两个字符串而不是两个数字。 It worked as expected, however it slowed down significantly, crashing the browser within the span of five seconds. 它按预期运行,但是速度大大降低,在五秒钟的时间内使浏览器崩溃。 I was wondering what the difference would be, performance-wise, between numbers and strings. 我想知道数字和字符串之间在性能方面的区别是什么。

My jsfiddle is here: https://jsfiddle.net/MCBlastoise/yrr7fL4z/54/ 我的jsfiddle在这里: https ://jsfiddle.net/MCBlastoise/yrr7fL4z/54/

And here is my code: 这是我的代码:

 var sequence = [0, 1]; var i = 2; function recursion() { recur = setInterval(fibonacci, 1); } function fibonacci() { var current = document.getElementById("text"); var a = sequence[i-2] + sequence[i-1]; sequence.push(a); if (current.innerHTML === "") { current.innerHTML = sequence[0] + ", " + sequence[1] + ", " + sequence[2]; } else { current.innerHTML = current.innerHTML + ", " + sequence[i]; } i++; }; function exactValue(position) { var current = document.getElementById("text"); if (isNaN(position) === false && position % 1 === 0 && position >= 1) { if (position === 1) { current.innerHTML = sequence[0]; } else if (position === 2) { current.innerHTML = sequence[1]; } else { while (i !== position) { var a = sequence[i-2] + sequence[i-1]; sequence.push(a); i++; } if (i === position) { current.innerHTML = "The value at position " + position + " is " + a + "."; } } } } function checkValue(value) { var current = document.getElementById("text"); if (isNaN(value) === false) { if (value === 0) { current.innerHTML = "The value provided appears at position " + 1 + "."; } else if (value === 1) { current.innerHTML = "The value provided appears at position " + 2 + "."; } else { while(a !== value && a !== Infinity) { var a = sequence[i-2] + sequence[i-1]; sequence.push(a); i++; } if (a === value) { current.innerHTML = "The value provided appears at position " + i + "."; return true; } if (a === Infinity) { current.innerHTML = "The value provided does not appear in this sequence."; return false; } } } } function clear() { document.getElementById("text").innerHTML = ""; } 
 <div onclick="recursion(), clear()" style="cursor:pointer; background-color:black; width:30px; height:30px"></div> <p id="text"></p> 

Well, loading numbers into memory and adding them can usually be compiled to just a few native CPU instructions, while concatenating Strings usually includes a lot of function calls through the whole language to produce a result. 好吧,将数字加载到内存中并添加它们通常可以只编译为一些本机CPU指令,而连接字符串通常包括整个语言中的许多函数调用以产生结果。 And I'm not sure how JavaScript handles strings internally, but growing a string could mean allocating a whole new byte array for each one. 而且我不确定JavaScript如何在内部处理字符串,但是增加字符串可能意味着为每个字符串分配一个全新的字节数组。

When you change the elements of the sequence array to be strings, the + operator in the following line will perform a completely different operation: 当您将序列数组的元素更改为字符串时,下一行中的+运算符将执行完全不同的操作:

var a = sequence[i-2] + sequence[i-1];

Instead of an arithmetic addition, this will be a string concatenation operation. 代替算术加法,这将是字符串串联操作。 This will involve a lot more memory and CPU time: 这将涉及更多的内存和CPU时间:

Addition of two numbers: 两个数字相加:

  • Time: constant, since an addition is performed as a CPU instruction, limited to the 64-bit float range. 时间:常量,因为加法是作为CPU指令执行的,因此限制为64位浮点范围。
  • Memory: one 64-bit float, since that is how numbers are represented in JavaScript. 内存:一个64位浮点数,因为这是用JavaScript表示数字的方式。

Concatenation of two strings: 两个字符串的串联:

  • Time: linear in terms of the length of the input strings: each character from both strings needs to be copied to a new memory location 时间:根据输入字符串的长度呈线性:两个字符串中的每个字符都需要复制到新的存储位置
  • Memory: doubles, as the final string occupies the same memory as the two input strings together 内存:加倍,因为最后一个字符串与两个输入字符串一起占用相同的内存

The memory impact will probably be the factor that kills the script: after only 20 iterations (ie calls to fibonacci ) the string value of a will have a length of over 10 000 characters, which will continue to almost double each next iteration. 内存影响可能是杀死脚本的因素:仅20次迭代(即调用fibonacci )后, a的字符串值的长度将超过10000个字符,而每次下一次迭代将继续几乎翻倍。 After 30 iterations, a will have more than a million characters. 经过30次迭代, a将拥有超过一百万个字符。 If you have enough patience to wait for the string copying of those megabytes to grow to gigabytes you'll find your PC's memory (the part available to the JavaScript box) has been eaten completely, probably before the 40th iteration. 如果您有足够的耐心等待这些兆字节的字符串复制增长到千兆字节,您会发现PC的内存(JavaScript框可用的部分)已被消耗eat尽,可能是在第40次迭代之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM