变量名长度的巨大差异怎么可能不会导致 javascript 的任何性能损失?
声明 var a = 0; 所需的时间与声明 var aaaaaaaaaaaaaaa = 0; 所需的时间相同
甚至用它们执行计算也需要相同的时间。
最佳答案
window.a = 2;
window.b = 3;
window.c = 4;
window.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 2;
window.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 3;
window.ccccccccccccccccccccccccccccccccccccccccccccccccc = 4;
var ts = [];
var t = performance.now();
for(var i = 0; i < 1000000; ++i) {
a = b + c;
}
ts.push(performance.now() - t);
var t = performance.now();
for(var i = 0; i < 1000000; ++i) {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+ ccccccccccccccccccccccccccccccccccccccccccccccccc;
}
ts.push(performance.now() - t);
console.log(ts);
在浏览器控制台中运行上述 10 次得到以下统计信息,即 a=b+c,a=b...+c... 对:
[4.050000000046566, 4.614999999990687]
[4.254999999946449, 4.59499999997206]
[4.054999999993015, 4.584999999962747]
[4.869999999995343, 5.4500000000116415]
[4.074999999953434, 4.570000000006985]
[4.099999999976717, 4.775000000023283]
[4.205000000016298, 4.649999999965075]
[4.205000000016298, 4.669999999983702]
[4.159999999974389, 4.720000000030268]
[4.149999999965075, 4.684999999997672]
较长的版本总是较慢。
在局部变量的情况下,这是不同的,因为它们被编译一次并通过索引而不是名称使用 getlocal/setlocal 指令引用。那么让我们看看..
(function() {
var a = 2;
var b = 3;
var c = 4;
var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 2;
var bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 3;
var ccccccccccccccccccccccccccccccccccccccccccccccccc = 4;
var ts = [];
var t = performance.now();
for(var i = 0; i < 1000000; ++i) {
a = b + c;
}
ts.push(performance.now() - t);
var t = performance.now();
for(var i = 0; i < 1000000; ++i) {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+ ccccccccccccccccccccccccccccccccccccccccccccccccc;
}
ts.push(performance.now() - t);
console.log(ts);
})();
[2.5850000000791624, 2.2100000000791624] (longer wins)
[2.7950000000419095, 2.525000000023283] (shorter wins)
[2.4699999999720603, 2.4200000000419095] (longer wins)
[2.64000000001397, 2.2449999999953434] (longer wins)
[2.669999999925494, 2.469999999855645] (longer wins)
[2.5200000000186265, 2.7800000000279397] (shorter wins)
[2.4600000000791624, 2.3950000000186265] (longer wins)
[3.2900000001536682, 3.1299999998882413] (longer wins)
[3.1949999999487773, 3.1850000000558794] (longer wins)
[3.8049999999348074, 3.0200000000186265] (longer wins)
虽然它们在大多数迭代中确实出人意料地不同,但在相当多的情况下,较长的变量名比较短的变量名更快(天真的观察者可能会得出结论,较长的名称使其更快)。这是因为名称仅在编译作用域时才相关;实际执行的指令不按名称引用变量。
我的结论是;保持全局变量名简短,局部变量名会略微增加从文本到指令的翻译,但在此之后,就没有关系了。
我假设 javascript 在处理变量方面与 actionscript 类似,所以这里是两个字节码并排的 actionscript 转储。 (Adobe Flash CS3;使用 JPEXS 免费 Flash 反编译器反编译)。
var a;
var b = 2;
var c = 3;
var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
var bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 2;
var ccccccccccccccccccccccccccccccccccccccccccccccccc = 3;
function long_global()
{
for(var i = 0; i < 1000000; ++i) {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccccccccccccccccccccccccccccccccc;
}
}
function short_global()
{
for(var i = 0; i < 1000000; ++i) {
a = b + c;
}
}
function long_local()
{
var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
var bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 2;
var ccccccccccccccccccccccccccccccccccccccccccccccccc = 3;
for(var i = 0; i < 1000000; ++i) {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccccccccccccccccccccccccccccccccc;
}
}
function short_local()
{
var a;
var b = 2;
var c = 3;
for(var i = 0; i < 1000000; ++i) {
a = b + c;
}
}
long_global 编译为:
; d0
getlocal_0
; 30
pushscope
; 21
pushundefined
; 82
coerce_a
; d5
setlocal_1
; 24 00
pushbyte 0
; 82
coerce_a
; d5
setlocal_1
; 10 0e 00 00
jump ofs001b
; 09
ofs000d:label
; 5e 0a
findproperty Qname(PackageNamespace(""),"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
; 60 09
getlex Qname(PackageNamespace(""),"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
; 60 06
getlex Qname(PackageNamespace(""),"ccccccccccccccccccccccccccccccccccccccccccccccccc")
; a0
add
; 68 0a
initproperty Qname(PackageNamespace(""),"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
; d1
getlocal_1
; 91
increment
; 82
coerce_a
; d5
setlocal_1
; d1
ofs001b:getlocal_1
; 2d 01
pushint 1000000
; 15 eb ff ff
iflt ofs000d
; 47
returnvoid
short_global 编译为
; d0
getlocal_0
; 30
pushscope
; 21
pushundefined
; 82
coerce_a
; d5
setlocal_1
; 24 00
pushbyte 0
; 82
coerce_a
; d5
setlocal_1
; 10 0e 00 00
jump ofs001b
; 09
ofs000d:label
; 5e 08
findproperty Qname(PackageNamespace(""),"a")
; 60 05
getlex Qname(PackageNamespace(""),"b")
; 60 04
getlex Qname(PackageNamespace(""),"c")
; a0
add
; 68 08
initproperty Qname(PackageNamespace(""),"a")
; d1
getlocal_1
; 91
increment
; 82
coerce_a
; d5
setlocal_1
; d1
ofs001b:getlocal_1
; 2d 01
pushint 1000000
; 15 eb ff ff
iflt ofs000d
; 47
returnvoid
long_local:
; d0
getlocal_0
; 30
pushscope
; 21
pushundefined
; 82
coerce_a
; d5
setlocal_1
; 21
pushundefined
; 82
coerce_a
; d6
setlocal_2
; 21
pushundefined
; 82
coerce_a
; d7
setlocal_3
; 21
pushundefined
; 82
coerce_a
; 63 04
setlocal 4
; 24 02
pushbyte 2
; 82
coerce_a
; d6
setlocal_2
; 24 03
pushbyte 3
; 82
coerce_a
; d7
setlocal_3
; 24 00
pushbyte 0
; 82
coerce_a
; 63 04
setlocal 4
; 10 0c 00 00
jump ofs002c
; 09
ofs0020:label
; d2
getlocal_2
; d3
getlocal_3
; a0
add
; 82
coerce_a
; d5
setlocal_1
; 62 04
getlocal 4
; 91
increment
; 82
coerce_a
; 63 04
setlocal 4
; 62 04
ofs002c:getlocal 4
; 2d 01
pushint 1000000
; 15 ec ff ff
iflt ofs0020
; 47
returnvoid
短本地化:
; d0
getlocal_0
; 30
pushscope
; 21
pushundefined
; 82
coerce_a
; d5
setlocal_1
; 21
pushundefined
; 82
coerce_a
; d6
setlocal_2
; 21
pushundefined
; 82
coerce_a
; d7
setlocal_3
; 21
pushundefined
; 82
coerce_a
; 63 04
setlocal 4
; 24 02
pushbyte 2
; 82
coerce_a
; d6
setlocal_2
; 24 03
pushbyte 3
; 82
coerce_a
; d7
setlocal_3
; 24 00
pushbyte 0
; 82
coerce_a
; 63 04
setlocal 4
; 10 0c 00 00
jump ofs002c
; 09
ofs0020:label
; d2
getlocal_2
; d3
getlocal_3
; a0
add
; 82
coerce_a
; d5
setlocal_1
; 62 04
getlocal 4
; 91
increment
; 82
coerce_a
; 63 04
setlocal 4
; 62 04
ofs002c:getlocal 4
; 2d 01
pushint 1000000
; 15 ec ff ff
iflt ofs0020
; 47
returnvoid
long_global和short_global的字节码大小;和 short_local 和 long_local 分别是等价的,但是在本地情况下,它们不是通过名称引用的,仅通过 setlocal 和 getlocal 引用;而在全局情况下,它们由字符串键所在位置的索引引用;我的猜测是,较长的一个需要更长的时间来散列以获取指示对象,而较短的一个需要更短的时间来散列以获取指示对象,然后才能使用它。
关于javascript - 变量名长度与性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31719887/
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"
我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi