我知道你可以使用PSR标准来定位文件,或者告诉composer一个目录来扫描类。**文档推荐使用PSR-4标准。**composer还有一个选项来创建optimized autoloader, which basically generates a full classmap。那么,如果加载的最佳方式是使用类Map,为什么还要使用PSR-4呢?
对我来说,保留目录结构是有意义的,因为这是一种很好的组织方式。然而,似乎合理的选择是在开发机器上使用PSR-4加载,然后在生产环境中使用类Map。这样,您不必在每次创建新类时都重新构建类Map。但生产环境会创建一个完整的虚拟机,作为部署过程的一部分,而无需额外调用
./composer.phar dump-autoload -o
7条答案
按热度按时间8tntrjer1#
问题是类Map实际上并不是在所有情况下都更快!
类Map的速度来自于在加载文件、解析文件(操作码缓存在这里会有帮助)和执行文件之前,不必检查文件系统是否存在。
但是类Map的缺点是,你可能会为你所使用的库中包含的每一个类、接口和trait生成大量的数据,而你并没有在你的生产代码中实际使用它。加载巨大的数组不是免费的--同时代码也不需要一遍又一遍地解析(操作码缓存),它仍然必须被执行,数组数据结构必须被放入内存,用大量的字符串填充,然后消耗掉一些本来可以用于其他事情的内存。
我找到了两个讨论此主题的资源:首先,github issue #1529建议进一步改进composer autoloader,使用一堆符号链接来避免扫描多个目录。
这里的讨论也揭示了你应该在PSR-0 autoload声明中使用尽可能好的名称空间前缀或类名前缀,也就是尽可能长的前缀,你也可以在声明中使用多个前缀。
然后是a blog post linked in that issue,它记录了一些xhprof基准测试,使用了一个常用的EZPublish 5并修改了设置,包括APC缓存和类Map转储。
报价:
这个命令创建了一个662KiB的vendor/composer/autoload_classmap.php文件,其中包含一个数组,该数组是一个散列,由类名作为索引,包含类定义的文件的路径作为值组成。在我写这篇文章的时候,这个数组由4168个条目组成。[...]虽然它应该给我们提供最有效的自动加载机制,它实际上降低了速度(从254.53请求/秒降低到197.95),原因是即使文件由APC缓存,每次请求都需要重新创建包含4100个以上条目的Map的PHP数组。
类Map会很快吗?当然。在所有情况下都是最快的吗?当然不是--这取决于每个请求中使用的类与未使用的类的比率。因此,即使平均而言,您的应用程序实际上使用了Map中的所有类,如果每个请求中只使用了大约10%的类,那么类Map仍然可能会较慢,并且您最好优化所使用库的自动加载声明。实际上,每个类名前缀应该只指向一个目录。
请注意,您所获得的性能提升仅限于每个请求的低个位数毫秒。如果这个数字是5%到10%范围内的显著性能提升,那么您的应用程序肯定是非常棒的。但是如果您确实处于该性能范围内,那么盲目地相信类Map总是更快可能会浪费大量不必要的CPU周期。
如果您优化某项内容:测量它!如果你不能测量它,你怎么知道它是否真的变好了呢?
frebpwbc2#
如果类Map实际上更快,为什么要在composer中使用PSR-0或PSR-4自动加载呢?
因为这样更实用。
在生产环境中,您可以使用classmap(带有
composer dumpautoload -o
),因为您不会添加任何新类,但在开发环境中,PSR-0或PSR-4提供的灵活性(即添加新类时无需执行任何操作)是很有趣的。composer install -o
,它更简单。qq24tv8q3#
如果您添加/更改了类,则需要执行以下操作:
***classmap:**composer转储加载(可能还需要使用新的classmap条目更新composer.json)
***psr-0:**无任何内容
***psr-4:**无结果
所以基本上你可以随意使用psr-4和psr-0而不用担心你新创建的类在autoloader中是否正确。2加上它你可以得到一个 free 正确的库目录结构,它代表你的命名空间。
自动加载器文件:
***类Map:**供应商/编译器/自动加载_类Map. php
***psr-0:**供应商/编写器/自动加载名称空间. php
***psr-4:**供应商/编写者/自动加载_psr4.php
pjngdqdw4#
这里一个重要的论点是,在composer.json中使用psr-4或psr-0会迫使你按照严格的标准来组织类文件,这会让其他人(或者2年后的你)看到composer.json时立即知道你的类在哪里。
如果你做错了,例如,如果你拼错了一个名称空间,那么你很可能会在开发或单元测试中发现,因为“类找不到”。这很好,因为它迫使你修复这个问题。
类Map要宽容得多,它允许任意组织类文件,让读者一无所知。
因此,正如其他人已经说过的那样:在composer.json中使用psr-4或psr-0,在开发过程中使用它,然后考虑在生产环境中使用-o选项,但是要衡量一下这是否真的带来了性能上的好处!
qyyhg6bp5#
PSR-0和PSR-4(以及类Map)的问题是,它的实现没有考虑到优化,实现充其量是缺乏的。
然而,类Map背后的思想是有效的。
我创建了一个可以生成类Map的库,但是这个类Map更简单,而且经过了优化。
https://github.com/eftec/autoloadone
即使对于一个大的项目,Map也会减少,如果类包含在同一个文件夹中,它会将相同名称空间的相同类分组。如果不是,那么它们也会被包含在内。同样,如果类缺少名称空间,一个文件中有两个类,文件在范围之外,这也不是问题,它会跟踪所有类。你甚至可以排除一些文件夹或名称空间。
比如在一个大项目中
因此,对于一个包含898个类的项目,Map只使用了12.9kb。
性能有何不同:
Composer的自动加载包括(对于每次调用)以下文件:
或者运行文件:
虽然Opcache确实令人惊叹,但我们仍然包括,至少,两个包括(而不是一个),加上其中一个是巨大的,它仍然是一个开销,它仍然是每个调用。
那么,哪个更快。这取决于项目,但我检查了通常PSR-0更快。然而,差异很小,两者都很慢。:-P
trnvg8h36#
概括起来,有两个概念:
1.建立文件Map,让composer知道要自动加载哪些文件。
1.为您的用例(开发与生产)生成最佳自动加载。
您可以使用PSR-0或PSR-4语法指定文件Map。
参考:www.example.comhttps://getcomposer.org/doc/04-schema.md#autoload
使用以下选项之一指定所需的自动加载实现(对于级别1优化):
还有其他优化选项(参见文档)
参考:https://getcomposer.org/doc/articles/autoloader-optimization.md
优化选项将确定将生成何种类型的自动加载。任何优化都不会生成非常适合于开发目的的普通文件查找自动加载。其他优化将使用类Map,该类Map对于生产使用通常更快,但在每次创建、重命名或移动类时都需要重新生成。
这种混淆可能源于这样一个事实,即自动加载配置也接受类Map格式:
但医生明确表示:
您可以使用类Map生成支持为所有不遵循PSR-0/4的库定义自动加载。
关键词是"库",它通常变化缓慢。
如果您的代码没有Map到PSR-0/4,请为其创建自己的自动加载器。
您可以使用composer的自动加载功能为新代码生成一个自动加载器,并注册该自动加载器和您自己的自动加载器,从而过渡到PSR-4。
ulydmbyx7#
这个问题是误导性的。
"classmap"作为autoloading选项更准确地说只是一个哑目录glob,它引用了遇到的每个具有匹配名称的类的文件。然后,它将所有这些编译到"classmap数组"中,其中也有PSR-0规则。
因此,PSR-0和类Map使用相同的类Map,这意味着实际上没有区别。
使用PSR-0是因为您希望自动加载PSR-0代码。