为什么字符串加载速度比数字慢很多?
Why do strings load so much slower than numbers?
我写了一个脚本,目的是对斐波那契数列进行排序(或者任何两个数字相加形成下一个数字,然后是这两个数字,等等)。当您按下一个按钮时,该函数(称为斐波那契)将两个值相加,将新值推入一个数组(称为序列),然后显示数组中的最新值。我用 setInterval
(称为递归)设置它,因此它会继续向数组添加更多值,并显示更多数字。我正在试验该函数,并想尝试使用两个字符串而不是两个数字。它按预期工作,但速度明显变慢,在五秒钟内使浏览器崩溃。我想知道数字和字符串之间在性能方面的区别是什么。
我的 jsfiddle 在这里:https://jsfiddle.net/MCBlastoise/yrr7fL4z/54/
这是我的代码:
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>
好吧,将数字加载到内存中并将它们相加通常可以编译成几条本机 CPU 指令,而连接字符串通常包括通过整个语言进行大量函数调用以产生结果。而且我不确定 JavaScript 如何在内部处理字符串,但增加一个字符串可能意味着为每个字符串分配一个全新的字节数组。
当您将 sequence 数组的元素更改为字符串时,下一行中的 +
运算符将执行完全不同的操作:
var a = sequence[i-2] + sequence[i-1];
这不是算术加法,而是字符串连接运算。这将涉及更多的内存和 CPU 时间:
两数相加:
- 时间:常量,因为加法是作为 CPU 指令执行的,限于 64 位浮点数范围。
- 内存:一个 64 位浮点数,因为这就是 JavaScript.
中数字的表示方式
两个字符串的连接:
- 时间:与输入字符串的长度成线性关系:两个字符串中的每个字符都需要复制到新的内存位置
- 内存:加倍,因为最终字符串与两个输入字符串一起占用相同的内存
内存影响可能是杀死脚本的因素:仅经过 20 次迭代(即调用 fibonacci)a[= 的字符串值32=] 的长度将超过 10 000 个字符,在每次下一次迭代中将继续增加几乎一倍。经过 30 次迭代后,a 将有超过一百万个字符。如果您有足够的耐心等待那些兆字节的字符串复制增长到千兆字节,您会发现您的 PC 内存(JavaScript 框可用的部分)已被完全占用,可能在第 40 次迭代之前。
我写了一个脚本,目的是对斐波那契数列进行排序(或者任何两个数字相加形成下一个数字,然后是这两个数字,等等)。当您按下一个按钮时,该函数(称为斐波那契)将两个值相加,将新值推入一个数组(称为序列),然后显示数组中的最新值。我用 setInterval
(称为递归)设置它,因此它会继续向数组添加更多值,并显示更多数字。我正在试验该函数,并想尝试使用两个字符串而不是两个数字。它按预期工作,但速度明显变慢,在五秒钟内使浏览器崩溃。我想知道数字和字符串之间在性能方面的区别是什么。
我的 jsfiddle 在这里:https://jsfiddle.net/MCBlastoise/yrr7fL4z/54/
这是我的代码:
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>
好吧,将数字加载到内存中并将它们相加通常可以编译成几条本机 CPU 指令,而连接字符串通常包括通过整个语言进行大量函数调用以产生结果。而且我不确定 JavaScript 如何在内部处理字符串,但增加一个字符串可能意味着为每个字符串分配一个全新的字节数组。
当您将 sequence 数组的元素更改为字符串时,下一行中的 +
运算符将执行完全不同的操作:
var a = sequence[i-2] + sequence[i-1];
这不是算术加法,而是字符串连接运算。这将涉及更多的内存和 CPU 时间:
两数相加:
- 时间:常量,因为加法是作为 CPU 指令执行的,限于 64 位浮点数范围。
- 内存:一个 64 位浮点数,因为这就是 JavaScript. 中数字的表示方式
两个字符串的连接:
- 时间:与输入字符串的长度成线性关系:两个字符串中的每个字符都需要复制到新的内存位置
- 内存:加倍,因为最终字符串与两个输入字符串一起占用相同的内存
内存影响可能是杀死脚本的因素:仅经过 20 次迭代(即调用 fibonacci)a[= 的字符串值32=] 的长度将超过 10 000 个字符,在每次下一次迭代中将继续增加几乎一倍。经过 30 次迭代后,a 将有超过一百万个字符。如果您有足够的耐心等待那些兆字节的字符串复制增长到千兆字节,您会发现您的 PC 内存(JavaScript 框可用的部分)已被完全占用,可能在第 40 次迭代之前。