为什么使用PSR-0或PSR-4自动加载composer php如果classmap实际上更快?
我知道你可以使用PSR标准来定位文件,或者告诉composer php一个目录来扫描类。 文档build议使用PSR-4标准。 composer php还有一个选项来创build一个优化的自动加载器,它基本上可以生成一个完整的类图 。 那么为什么要使用PSR-4,如果最好的加载方式是使用类图呢?
保持目录结构对我来说是有意义的,因为这是一个很好的组织方式。 但是,似乎合乎逻辑的select是在开发机器上使用PSR-4,然后在生产环境中使用classmap。 这样,每次创build新类时都不必重新生成类映射,但是生产环境将创build一个完整的类作为部署过程的一部分,而无需额外的调用
./composer.phar dump-autoload -o
为什么使用PSR-0或PSR-4自动加载composer php如果classmap实际上更快?
因为它更实用。
在制作中,你可以使用一个classmap(带有composer dumpautoload -o
),因为你不会添加任何新的类,但是在dev环境中,PSR-0或者PSR-4提供的灵活性很有趣增加新的类)。
更新:你也可以使用composer install -o
,这是更简单。
问题在于,在任何情况下,类映射实际上并不快!
classmap的速度来自于不必在文件加载之前检查文件系统是否存在,parsing它(操作码caching在这里有帮助),然后执行它。
但是,类图的不利之处在于,您可能会为包含在您使用的库中的每个类,接口和特征生成大量数据,而实际上并未在生产代码中使用它。 加载巨大的数组并不是免费的 – 虽然代码不需要一次又一次的parsing(操作码高速caching),但它仍然需要执行,数组数据结构必须被放入内存,充满大量的string,然后吃了一些可能用于别的东西的内存。
我发现讨论这个主题的两个资源:首先是github问题#1529,build议使用一堆符号链接进一步改进作曲者自动加载器,以避免扫描多个目录。
在那里的讨论还显示,你应该尝试在PSR-0自动装载声明中使用尽可能好的命名空间或类名前缀,即最长的一个。 您也可以在声明中使用多个前缀。
然后在那个问题上有一个博客文章,它使用一个股票EZPublish 5logging了一些xhprof基准,并且摆弄了包括APCcaching和分类转储在内的设置。
货币报价:
该命令创build了一个662KiB vendor / composer / autoload_classmap.php文件,其中包含一个由作为索引的类名和包含类定义的文件的path组成的散列值的数组。 在写这篇文章的时候,这个数组是由4168个条目组成的。 虽然它应该给我们提供最有效率的自动加载机制,但它实际上减慢了速度(从254.53 /秒到197.95)。 原因是,即使文件被APCcaching,包含超过4100个条目的地图的PHP数组也需要在每个请求中重新创build。
一个类图会快吗? 当然。 在每一种情况下最快? 当然不是 – 这取决于每个请求使用的比率和未使用的类别。 所以即使你的应用程序实际上使用了映射中的所有类,如果你只使用每个请求的10%左右的类,那么类映射仍然会变慢,而且你最好优化你使用的库的自动载入声明。 实际上,每个类名前缀只能指向一个目录。
请注意,您只能达到的性能增益大约是每个请求的低单位数毫秒。 如果这个数字在5%到10%的范围内有显着的性能提升,那么你的应用肯定是非常棒的。 但是如果你真的处于这样的性能范围内,一味地认为类图速度更快可能会浪费大量不必要的CPU周期。
如果你优化一些东西:测量它! 你怎么知道如果你不能测量它真的会变得更好?
如果您添加/更改了类,则需要执行以下操作:
- classmap: composer dumpautoload(也许还会用新的classmap条目更新composer.json)
- psr-0:什么也没有
- psr-4:什么都没有
所以基本上你可以用psr-4和psr-0去狂野,而不必担心新创build的类是否在自动加载器中是正确的。 再加上它,你会得到一个免费的适当的目录结构,它代表你的名字空间。
自动加载器文件:
- classmap: vendor / composer / autoload_classmap.php
- psr-0: vendor / composer / autoload_namespaces.php
- psr-4: vendor / composer / autoload_psr4.php
这里一个重要的论点是,在composer.json中使用psr-4或psr-0会迫使你按照严格的标准来组织你的类文件。 这允许看着composer.json的其他人(或者从现在开始2年)立即知道你的课程在哪里。
如果你这样做是错误的,例如,如果拼错一个命名空间,那么在开发过程中或者在你的unit testing中,由于“未find类”,你可能会发现这个错误。 这很好,因为这会迫使你解决这个问题。
类图更加宽容,并且允许任意组织的类文件,让读者在黑暗中。
所以,正如其他人所说的那样:在composer.json中使用psr-4或psr-0,在开发过程中使用psr-4或psr-0,然后考虑生产的-o选项。 但是,如果这真的带来性能上的好处!
问题是误导。
作为自动加载选项的“classmap”更准确地说是一个愚蠢的目录glob,它引用了每个遇到的具有匹配名称的类的文件。 然后把所有这些编译到“classmap array”中,这里还有PSR-0规则。
所以,PSR-0和classmap使用相同的classmap,意思是没有区别。
您使用PSR-0是因为您要自动加载PSR-0代码。