我正在开发一个每秒可以看到几十个并发用户的Web应用程序。我有一个类将在同一页面加载中多次实例化。在该类中,我有一些属性在每个对象中始终是相同的,所以我正在考虑将这些属性声明为static
,以减少在此类的多个实例时将使用的内存在同一页面请求中实例化。
这样做会为这个应用程序使用更少的内存,因为PHP只能存储一次静态属性的值吗?这样做会在并发用户之间节省内存吗,还是只在每个PHP进程中节省内存?
这对方法有何用处?如果这意味着对象可以循环使用相同的方法,那么为什么在尝试保存内存时,不会将类的所有方法声明为静态?
我不清楚为什么以及何时声明属性或方法是静态的,但我确实理解将它们声明为静态允许在不实例化类的对象的情况下访问它们(这感觉就像一个黑客......这些方法和属性应该在其他地方......不是吗?)。我特别感兴趣的是static
声明影响内存使用的方式,以便在我的网络服务器上尽可能降低内存使用率......总的来说,我对发生的事情有了更好的理解
答案 0 :(得分:16)
当您将类方法/变量声明为静态时,它将被绑定并由类共享,而不是对象。从内存管理的角度来看,这意味着当类定义加载到堆内存中时,会在那里创建这些静态对象。当在堆栈内存中创建类的实际对象时,并且在完成静态属性的更新时,将更新包含静态对象的堆的指针。这确实有助于减少记忆,但不是很多。
从编程范式来看,人们通常选择使用静态变量来获得架构优势而不是内存管理优化。换句话说,当你想要实现单例或工厂模式时,可能会像你提到的那样创建静态变量。它提供了更强大的方法来了解“类”级别的内容,而不是“对象”级别的内容。
答案 1 :(得分:5)
看静态与单身测试:http://moisadoru.wordpress.com/2010/03/02/static-call-versus-singleton-call-in-php/
注意:由于某些原因,stackoverflow没有显示multilne主题,所以我正在添加图片。
Number of runs Singleton call time (s) Static call time (s)
100 0.004005 0.001511
1,000 0.018872 0.014552
10,000 0.174744 0.141820
100,000 1.643465 1.431564
200,000 3.277334 2.812432
300,000 5.079388 4.419048
500,000 8.086555 6.841494
1,000,000 16.189018 13.696728
答案 2 :(得分:4)
在PHP中使用静态方法和属性是否使用更少的内存?
可能。但是,为什么你会搞乱你的OOP架构呢?
这有关系吗?
可能不是。需要记忆的是PHP本身。我坚决认为删除几个字节因为你使用静态方法不会有所作为。相反,不要加载无用的模块。例如,如果您不使用GD,请不要加载它。激活缓存以减少调用PHP的次数。
答案 3 :(得分:1)
静态方法调用在许多次迭代中更快,但静态方法并不能真正节省内存。
如果您声明的类没有任何需要对每个对象实例唯一的属性,那么您可以将每个方法和属性声明为静态。但是,如果您具有需要绑定到每个对象的属性,则静态方法没有帮助。原因是因为在静态方法中,没有对$this
的引用,因此您无法从静态方法引用对象属性。
阅读Static Keyword,以便更好地了解这一点。
答案 4 :(得分:1)
一般来说,是的。静态方法和属性使用较少的内存。但是,差异非常小。
更有趣的是performance difference between static and non-static methods。
答案 5 :(得分:0)
我不是PHP内存管理方面的专家,但我会说你不会节省太多。如果和节省多少取决于某些方面:
特别是对象的数量很重要。如果您只有一个实例,则可以节省50%。在这种情况下:
案例A - 静态:您没有实例化对象,只是使用存储在内存中的类定义。但是每个REQUEST都会加载类定义,这意味着内存中的类定义与并发请求的数量相同。
案例B - 实例:除了案例A之外,每个请求还有一个此对象的实例,因此这部分软件的内存使用量增加了一倍。
最后:如果你更容易使用静态参数而不是每次实例化类,你应该采用静态方式。但是不要指望太多的记忆力提升。
答案 6 :(得分:0)
我刚刚改进了斯坦尼斯拉夫链接的基准,使其能够正常运行:
Results for PHP 7.4.1:
Runs by case: 500000
Memory usage at start: 426,320
Run Duration % Memory
Dynamic 0.0594 30% 496
Dynamic instantiated 0.0917 46% 0 #
Dynamic instantiated stored 0.1994 100% 48,967,472 # slowest
Storage only 0.0422 21% 16,781,392
Cost of instations only when stored 0.1572 79% 32,186,O8O # cost of stored instatiations minus storage cost (diff of 2 previous lines)
Static 0.0870 44% 0 # equivalent to dynamic with instantiation
Singletons with many getInstance 0.1213 61% 376
Singletons with one getInstance 0.0669 34% 320 # equivalent to "Dynamic"
Functions assigning $GLOBALS 0.0605 30% 0 # more than 2 times longer than using "global"
Functions assigning a global 0.0458 23% 32 # fastest. 32bits allocated? probably passed by copy... odd
Functions with $counter by ref 0.0707 35% 0 # slow for functions
Functions with $counter static prop 0.0524 26% 0
备注:
开发人员实践的结论(于2020年1月生效):
欢呼
PS:由于结果限制,即使结果不是100%稳定,我也无法进行更多运行(在整个工作台刷新后,我看到20%的变化) PS 2:如果要禁用3v4l.org的缓存,只需在代码中的任意位置添加一个空格
答案 7 :(得分:-1)
如果您共享数据,请使用静态。它更快,并为您节省了对象实例化的过程。当你需要一个入口点时,单身人士会胜过静态。我在大约一周前在我的博客上报道了这一点。