php 获取对象所有成员变量,PHP成员变量获取对比

有如下4个代码示例,你认为他们创建对象,并获得成员变量的速度排序是怎样的?

1:将成员变量设置为public,通过赋值操作给成员变量赋值,直接获取变量

class Foo { public $id; }   $data = new Foo; $data->id = 10; echo $data->id;

2:将成员变量设置为public,通过构造函数设置成员变量的值,直接获取变量

class Foo2 { public $id; public function __construct($id) { $this->id = $id; } }   $data = new Foo2(10); echo $data->id;

3:将成员变量设置为protected,通过构造函数设置成员变量的值,通过成员方法获取变量

class Foo3 { protected $id; public function __construct($id) { $this->id = $id; }   public function getId() { return $this->id; } } $data = new Foo3(10); echo $data->getId();

4:将成员变量设置为protected,通过构造函数设置成员变量的值,通过魔术方法获取变量

class Foo4 { protected $id; public function __construct($id) { $this->id = $id; }   public function __get($key) { return $this->id; } } $data = new Foo4(10); echo $data->id;

按执行速度快慢排序: 1243

咱们先看其opcode:

1:

1 ZEND_FETCH_CLASS 4 :4 'Foo' 2 NEW $5 :4 3 DO_FCALL_BY_NAME 0 4 ASSIGN !0, $5 5 ZEND_ASSIGN_OBJ !0, 'id' 6 ZEND_OP_DATA 10 7 FETCH_OBJ_R$9 !0, 'id' 8 ECHO $9

2:

1 ZEND_FETCH_CLASS 4 :10 'Foo2' 2 NEW $11 :10 3 SEND_VAL 10 4 DO_FCALL_BY_NAME 1 5 ASSIGN !1, $11 6 FETCH_OBJ_R$14 !1, 'id' 7 ECHO $14

3:

1 ZEND_FETCH_CLASS 4 :15 'Foo3' 2 NEW $16 :15 3 SEND_VAL 10 4 DO_FCALL_BY_NAME 1 5 ASSIGN !2, $16 6 ZEND_INIT_METHOD_CALL !2, 'getId' 7 DO_FCALL_BY_NAME 0 $20 8 ECHO $20

4:

1 ZEND_FETCH_CLASS 4 :21 'Foo4' 2 NEW $22 :21 3 END_VAL 10 4 DO_FCALL_BY_NAME 1 5 ASSIGN !3, $22 6 FETCH_OBJ_R $25 !3, 'id' 7 ECHO $25

根据上面的opcode,参照其在zend_vm_execute.h文件对应的opcode实现,我们可以发现什么?

一、PHP内核创建对象的过程分为三步:

ZEND_FETCH_CLASS 根据类名获取存储类的变量,其实现为一个hashtalbe EG(class_table) 的查找操作

NEW 初始化对象,将EX(call)->fbc指向构造函数指针。

调用构造函数,其调用和其它的函数调用是一样,都是调用zend_do_fcall_common_helper_SPEC

二、魔术方法的调用是通过条件触发的,并不是直接调用,如我们示例中的成员变量id的获取(zend_std_read_property),其步骤为:

获取对象的属性,如果存在,转第二步;如果没有相关属性,转第三步

从对象的properties查找是否存在与名称对应的属性存在,如果存在返回结果,如果不存在,转第三步

如果存在__get魔术方法,则调用此方法获取变量,如果不存在,报错

回到排序的问题:

一、第一个和第二个的区别是什么?

第二个的opcode比第一个要少,反而比第一个要慢一些,因为构造函数多了参数,多了一个参数处理的opcode。参数处理是一个比较费时的操作,当我们在做代码优化时,一些不必要的参数能去掉就去掉;当一个函数有多个参数时,可以考虑通过一个数组将其封装后传递进来。

二、为啥第三个最慢?

因为其获取参数其本质上是一次对象成员方法的调用,方法的调用成本高于变量的获取

三、为啥第四个比第三个要快?

因为第四个的操作实质上获取变量,只不过其内部实现了魔术方法的调用,相对于用户定义的方法,内部函数的调用的效率会高。因此,当我们有一些PHP内核实现的方法可以调用时就不要重复发明轮子了。

四、为啥第四个比第二个要慢?

因为在PHP的对象获取变量的过程中,当成员变量在类的定义不在在时,会去调用PHP特有的魔术方法__get,多了一次魔术方法的调用。

总结一下:

使用PHP内置函数

并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

尽量少用魔术方法 -- 除非有必要,不要用框架,因为框架都有大量的魔术方法使用。

在性能优先的应用场景中,将成员变量设置为public,不失为一种比较好的方法,当你需要用到OOP时。

能使用PHP语法结构的不要用函数,能使用内置函数的不要自己写,能用函数的不要用对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

32位应用程序单个进程最大占用内存是4GB

32位应用程序单个进程最大占用内存是4GB左右,这个问题是因为需要测试大数据里才能体现出来的问题,所以反反复复花了一周多的时间来搞定它,希望大家在对它有一个印象。64位的应用程序的时候就不会有这个限制。所以这种情况下请编译成64位的程序…

【Blog.Core开源】快速升级.NET 6.0

BCVP只要贡献,就不分大小,每个人都是这个时代最璀璨的星!一个以开源项目主导的社区组织。《Blog.Core》开源项目已经3年,期间收获了很多很多,同时也收到了很多小伙伴的支持和鼓励,才使得我有足够的心力从2.…

全网爆红!全新洗脑神曲:程序员Disco

作曲 : 宝石gem作词 : 宝石gem作词改编:云信刘亦菲产品:这个需求明天就得实现开发:至少2周产品:就3天,是不是干不了开发:开玩笑,加班也要1周多产品:4天,有啥困难我帮你跟…

SiteMapCreator 发布 (Open Source)

Site Map Creator (Open Source) Introduction Site Map是asp.net里面很方便的一个站点导航的控键。使用它,只需要简单的配置一下xml文件,就能够控制页面流。但是用手去编写SitMap的xml文件实在太麻烦了,因此我写了这个小软件,并…

eclipse默认编码为GBK,修改为UTF8的方法

2019独角兽企业重金招聘Python工程师标准>>> eclipse 默认编码居然是GBK,js文件默认编码是ISO-....怎么可以这样呢?都修改成UTF8的方法:1、windows->Preferences...打开"首选项"对话框,左侧导航树&#x…

php中页面平滑回到顶部代码,原生JS实现平滑回到顶部组件_javascript技巧

返回顶部组件是一种极其常见的网页功能,需求简单:页面滚动一定距离后,显示返回顶部的按钮,点击该按钮可以将滚动条滚回至页面开始的位置。实现思路也很容易,只要改变document.documentElement.scrollTop或document.bod…

在Word XP中也能插入国际音标、拼音

在wps2000 中可以轻松地插入国际音标和汉语拼音,但是利用它输入的汉语拼音和国际音标只能够在WPS2000中打印输入,无法到别的软件中进行再编辑。同时尽管Word XP具有符号插入的功能,但是无论如何都找不到国际音标和汉语拼音,不过&a…

数学有多震撼?!我真的没有在开车!

让我们来欣赏一下日本高校欧派函数(おっぱい関数)对抗大赛中的作品吧。埼玉大学(理学部)其中 明治大学広島大学(理学部)東京農業大学其中 是一个可调常数,下图中p3。文教大学京都大学其中首都大…

一些微服务拆分的浅见

大家好,我是Z哥。不管是十几年前 SOA 的流行,还是 7、8 年前微服务的大行其道,还是如今云原生的展露锋芒,背后都离不开一件事,程序拆分或者说服务拆分。否则,一个单体应用,以上的这些技术潮流好…

centos 6.0安装杀毒软件clamAV 0.98

1、查看系统版本[rootlocal]# lsb_release -aLSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarchDistributor ID: CentOSDescription: CentOS release 6.4 (…

php post api json数据,php – REST API:请求身份为JSON或纯POST数据?

POST,PUT,GET都是HTTP动词,并且本身并不表示传输数据的格式,因此没有POST格式。这意味着您可以按照您选择的任何方式对数据进行编码。现在,你决定采用什么样的格式,真的应该是一个API通常被使用的问题。如果…

命令行下的mysql的基本操作

1.登录数据库 MySQL -h localhost -u root -p Enter password:**** 如果信息正确,出现数据库名字 2.关闭MySQL net stop MySQL 关闭 net start MySQL 启动 3.登录成功后,显示当前数据库已有数据 show database; 4.建立数据库 drop database i…

大变天!刚刚,山东突然宣布!关乎800万人...

全世界只有3.14 % 的人关注了青少年数学之旅由山东省大数据局主办、青岛市大数据发展管理局承办的山东省数据应用(青岛)创新创业大赛自9月23日启动以来,凭借着新颖赛题、丰富数据和丰厚奖励,吸引了社会各界数据爱好者与从业者的广…

MassTransit中RequestResponse基本使用

MassTransit 是一个自由、开源、轻量级的消息总线基于.Net框架, 用于创建分布式应用程序。方便搭建基于消息的松耦合异步通信的应用程序和服务。MassTransit 在现有消息传输上提供了一组广泛的功能, 从而使开发人员能够友好地使用基于消息的会话模式异步连接服务。基于消息的通…

ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效

今天项目展示,但是有些数据不是特别规范,我就直接使用Toad去操作数据库中的数据。结果在修改某一张表的时候就出现了上述错误,表示十分无奈。 出错原因分析: 首先执行如下语句: SELECT sid, serial#, username, osuser…

php2612,达人曝光LGLSNJ2612AR质量好吗?怎么样呢?体验报告揭秘

其实这个LGLSNJ2612AR还可以的 哟,超凡的造型设计和外观,做工细腻,不少的人想要了解这LGLSNJ2612AR怎么样?质量好不好?实实在在的说这款LGLSNJ2612AR使用体验后个人感觉蛮可以的哈,刚购没多久的&#xff0c…

数据仓库的 RDBMS 性能优化指南

转:http://www.microsoft.com/china/technet/prodtechnol/sql/2000/maintain/c2061.asp数据仓库的 RDBMS 性能优化指南 本性能优化指南旨在帮助数据库管理员和开发人员配置 Microsoft SQL Server™ 2000,以获得最佳的性能,并帮助找出造成关系…

JAVA反射使用手记

JAVA反射使用手记 本篇文章为在工作中使用JAVA反射的经验总结,也可以说是一些小技巧,以后学会新的小技巧,会不断更新。本文不准备讨论JAVA反射的机制,网上有很多,大家随便google一下就可以了。 在开始之前,…

说普通话时舌头卷不起来是一种什么体验?| 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅

使用Lucene.Net实现全文检索

Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。开发人员可以基于Lucene.net实现全文检索的功能。Lucene.net是…