使用开关:
switch($page){
case 'dog':
case 'cat':
case 'robot':
case 'default':{
break;
};
default:{
break;
}
}
如果:
if($page == 'dog' || $page == 'cat' || $page == 'robot' || $page == 'default'){
}else{
}
使用针和干草堆:
$pages = array('dog', 'cat', 'robot', 'default');
if(in_array($page, $pages)){
}else{
}
I would like to know what is happening under-the-hood.
最佳答案
所有使用 VLD 输出的场景(PHP 5.6.4)
切换
number of ops: 31
compiled vars: !0 = $page
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > EXT_STMT
1 ASSIGN !0, 'default'
3 2 NOP
4 3 EXT_STMT
4 CASE ~1 !0, 'dog'
5 > JMPZ ~1, ->7
5 6 > > JMP ->10
7 > EXT_STMT
8 CASE ~1 !0, 'cat'
9 > JMPZ ~1, ->11
6 10 > > JMP ->14
11 > EXT_STMT
12 CASE ~1 !0, 'robot'
13 > JMPZ ~1, ->15
7 14 > > JMP ->18
15 > EXT_STMT
16 CASE ~1 !0, 'default'
17 > JMPZ ~1, ->23
18 > NOP
9 19 EXT_STMT
20 > BRK 1, ->30
11 21* EXT_STMT
22* JMP ->25
23 > EXT_STMT
24 > JMP ->29
25 > NOP
13 26 EXT_STMT
27 > BRK 1, ->30
15 28* JMP ->30
29 > > JMP ->25
16 30 > > RETURN 1
如果
number of ops: 16
compiled vars: !0 = $page
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > EXT_STMT
1 ASSIGN !0, 'default'
3 2 EXT_STMT
3 IS_EQUAL ~1 !0, 'dog'
4 > JMPNZ_EX ~1 ~1, ->7
5 > IS_EQUAL ~2 !0, 'cat'
6 BOOL ~1 ~2
7 > > JMPNZ_EX ~1 ~1, ->10
8 > IS_EQUAL ~3 !0, 'robot'
9 BOOL ~1 ~3
10 > > JMPNZ_EX ~1 ~1, ->13
11 > IS_EQUAL ~4 !0, 'default'
12 BOOL ~1 ~4
13 > > JMPZ ~1, ->15
5 14 > > JMP ->15
针和干草堆
number of ops: 17
compiled vars: !0 = $page, !1 = $pages
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > EXT_STMT
1 ASSIGN !0, 'default'
3 2 EXT_STMT
3 INIT_ARRAY ~1 'dog'
4 ADD_ARRAY_ELEMENT ~1 'cat'
5 ADD_ARRAY_ELEMENT ~1 'robot'
6 ADD_ARRAY_ELEMENT ~1 'default'
7 ASSIGN !1, ~1
4 8 EXT_STMT
9 EXT_FCALL_BEGIN
10 SEND_VAR !0
11 SEND_VAR !1
12 DO_FCALL 2 $3 'in_array'
13 EXT_FCALL_END
14 > JMPZ $3, ->16
6 15 > > JMP ->16
9 16 > > RETURN 1
如您所见,开关实际上具有最多的操作,但在您的测试用例中是最快的(有兴趣看到它,因为我想这些方法中的每一个在特定情况下都可能是“最佳”)
虽然操作不是标准的工作量,但它们确实给出了指示。
一点比较
Switch 使用了很多CASE(检查两个值是否相等)和JMPZ(如果地址为零则跳转)。
If 语句使用 IS_EQUAL,这与 case 类似,但第二个值必须是常量。我认为这会减慢检查速度,因为现在有 2 个变量可以检查。 (您的基准测试结果似乎与此一致)
接下来使用函数调用。函数在 PHP 中通常被认为很慢 https://github.com/php/php-src/blob/df29df7ec40cf7950a98f36bfa99ef19f0950309/ext/standard/array.c#L1595
是函数的 C 源代码,每种类型的变量都有不同的逻辑。假设我们使用的是字符串,数组被循环并用
检查每个值尽可能早点回来。
基准脚本
$max_checks = 1000000;
$bench = -microtime(true);
for($i = 0;$i < $max_checks; $i++) {
switch($page){
case 'dog':
case 'cat':
case 'robot':
case 'default':{
break;
};
default:{
break;
}
}
}
echo "\nSwitch took " . (microtime(true) + $bench);
$bench = -microtime(true);
for($i = 0;$i < $max_checks; $i++) {
$page == 'dog' || $page == 'cat' || $page == 'robot' || $page == 'default';
}
echo "\nif took " . (microtime(true) + $bench);
$pages = array('dog', 'cat', 'robot', 'default');
$bench = -microtime(true);
for($i = 0;$i < $max_checks; $i++) {
(in_array($page, $pages));
}
echo "\nneedle haystack took " . (microtime(true) + $bench);
传入 $page = 'dog';
Switch took 0.31698203086853
if took 0.18721604347229
needle haystack took 1.5701420307159
传入 $page = 'default';
Switch took 0.46866297721863
if took 0.40072298049927
needle haystack took 1.6747360229492
传入$page = 'no match';
Switch took 0.52629804611206
if took 0.40276217460632
needle haystack took 1.6838929653168
我不确定你使用的是什么输入,但 if 和 switch 对我来说很相似(switch 的边缘更具可读性)
编辑:
1 个更快的测试用例。
使用 if 和 ===
这会将 IS_EQUAL 调用替换为 IS_IDENTICAL
有轻微的加速
所有测试用例
if took 0.43217587471008
if(===) took 0.39284706115723
操作码列表 http://php.net/manual/en/internals2.opcodes.list.php
编辑数字 2
因为无论如何我都在测试 PHP 7 RC3。
基准测试重新运行(在同一台机器上)
$page = '狗';
Switch took 0.018393993377686
if took 0.030646085739136
if(===) took 0.036449909210205
needle haystack took 0.045974969863892
$page = 'default';
Switch took 0.040921211242676
if took 0.085216999053955
if(===) took 0.1043848991394
needle haystack took 0.052649974822998
$page = '不匹配';
Switch took 0.059795141220093
if took 0.080615997314453
if(===) took 0.10486197471619
needle haystack took 0.049200057983398
在 PHP 7 中,针和大海捞针看起来最好
关于php - 在这些条件下发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32637827/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden