有什么方法可以避免为非 oo 应用程序加载未使用的类吗?
我的应用程序使用一个“中央”页面控制器,在获取请求之前使用 require_once 来获取一堆文件(我犹豫是否要说库),每个文件都包含一些相关的类。如:
require_once (dir_lib . 'db.php');
require_once (dir_lib . 'uuid.php');
require_once (dir_lib . 'data.php');
require_once (dir_lib . 'token.php');
require_once (dir_lib . 'logs.php');
require_once (dir_lib . 'time.php');
等等...
直到最近安装了(很棒但巨大的)“HTML Purifier”库并浏览了它的自动加载器,我才费心检查内存使用情况。显然,如果不启用自动加载器,每个脚本实例现在的内存使用量将高达(天哪!)5376 KB。 (如果这就是最终结果,我不知道内置自动加载器是做什么用的,但我离题了)如果没有 HTML Purifier,大多数实例的重量仍然超过 1 MB。
阅读有关 PHP 自动加载函数 我的印象是自动加载器是严格意义上的对于面向对象编程。除了净化器库之外,我使用的面向对象代码非常少。我只是误解了这个概念吗?有没有其他实用的方法来避免盲目加载一堆每个请求可能不需要的类?我是否只是懒惰地尝试将它们全部包含在内?
编辑 -
在这里重复此评论以澄清我所说的非 oo 的含义,如果这有很大区别的话:
我是 基本上使用类代替 不使用(几乎)任何名称空间 实际的面向对象编程。也就是说, “DBFunctions”类可能包含,对于 例如,函数“执行”和 “获取行”。函数被调用 使用静态方法调用,例如 “dbFunctions::执行($sql)。”
My application uses a 'central' page controller that grabs a bunch of files (I hesitate to say libraries) each containing a few related classes, using require_once, before fetching the request. As in:
require_once (dir_lib . 'db.php');
require_once (dir_lib . 'uuid.php');
require_once (dir_lib . 'data.php');
require_once (dir_lib . 'token.php');
require_once (dir_lib . 'logs.php');
require_once (dir_lib . 'time.php');
etc...
I haven't bothered to check memory usage until recently installing the (awesome, but gigantic) 'HTML Purifier' library and glancing at its autoloader. Apparently, autoloader on not, each script instance now weighs in at a whopping (sweet jesus!) 5376 kilobytes memory usage. (I have no idea what the built-in autoloader is for if that's the end result, but I digress) Without the HTML Purifier, most instances still weight in at over a megabyte.
Reading about the PHP autoload functions I'm getting the impression that the autoloader is meant strictly for OOP. With the exception of the purifier library, I'm using very little object-oriented code. Am I just misunderstanding the concept? Is there any other practical way to avoid blindly loading a bunch of classes that may not be needed for each request? Am I just being lazy for trying to include them all up-front?
EDIT -
Repeating this comment up up here to clarify what I meant by non-oo, if that makes much difference:
I am
basically using classes in lieu of
namespaces without using (hardly) any
actual OOP. That is to say, the
"DBFunctions" class may contain, for
example, the functions "execute" and
"getRow". The functions are invoked
with a static method call such as
"dbFunctions::execute($sql)."
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这些函数文件不是类有什么特殊原因吗?我唯一能想到的是 PHP4 兼容性,但 PHP4 中无论如何都不存在自动加载。
只需将这些现有代码文件包装在
class DBFunctions { ... }
中,并在函数调用前添加DBFunctions::
前缀以进行匹配,就足以让自动加载器开始工作(设置 spl_autoload_register() 回调以适应之后),这是值得的。如果您想保持代码的这种方式,那么它在风格上仍然是程序性的,如果您想这样做,那么它是向 OOP 化整个代码库迈出的一个不错的一步。(HTML Purifier 是一头大象,你检查过 PHP 内部的 filter 函数吗?)
Is there a particular reason for those function files to not be classes? The only one I can think of would be PHP4 compatibility, but autoload doesn't exist in PHP4 anyway.
Just wrapping those existing code files in
class DBFunctions { ... }
and prefixing your function calls withDBFunctions::
to match should be enough to let the autoloader go to work (after setting an spl_autoload_register() callback to suit), and it's worth it. It's still stylistically procedural if you wanted to keep the code that way, and a decent step towards OOPifying your whole code base should you want to go that way.(And HTML Purifier is an elephant, have you checked out PHP's internal filter functions?)
使用自动加载不会影响性能,因为类本身在被调用或使用之前不会被加载。自动加载结构基本上根据需要加载类,因为它们还没有被实例化。
在代码中找到首先实例化该类的位置。除非类文件自动实例化,否则它不应该占用任何内存。也许并非所有内容都已实例化,但在不需要时不会取消设置。
当您找到每个实例的实例化位置或您可以使用的相关实例时:
您可以使用
memory_get_peak_usage()
通过放置一些断点来处理它。现在尝试同样的事情,但这次在使用类之后使用 unset() :
所以基本上理论上,在应用程序中取消设置任何未使用的实例,查找大对象,进行调试。
这是为了澄清 @greg 对 OOP 的评论:
将此块作为示例:
输出:
上面的示例是因为引用了一个使用 OOP 的函数,在本例中是类私有变量
$run
。由于该类未实例化(对象实例),因此会出错。所以,是的,您可以通过引用使用类内部的函数,但它们大多必须是简单的过程引用或常量引用。希望这有帮助。
Using Autoload shoudn't hit performance as the class them selves aren't loaded until they are called or used. Autoload contruct basically loads class as needed is they haven't been instanciated already.
Find in the code where the class is been instanciated first. Unless class files are instanciated automatically, it shoudn't take any memory. Maybe not all are been instanciated, but not unset when not needed.
When you find where each is been instanciated or the one in question you can use then:
You can handle it by placing some break points, using
memory_get_peak_usage()
.Now try the same thing but this time using unset() after class have been used:
So basically in theory, unset any unused instance across app, find large objects, debug.
This is to clarify @greg's comments regards OOP:
Take this chunk as sample:
Output:
The above sample because is referencing a function which uses OOP, in this case the class private variable
$run
. Since the class isn't instantiated(an object instance), it will error out. So, yes you can use functions inside of a class by reference but they mostly have to be plain procedural or constant references.Hope this help.
PHP5 的自动加载仅适用于动态加载类。您的应用程序中只能使用一种自动加载功能(但请参见下文)。有关详细信息,请阅读自动加载文档。基本上,您可以定义一个 __autoload() 函数,当 PHP 尝试调用尚未加载的类时,该函数将加载您想要的任何文件(或执行您想要的任何操作),其中包含您想要的任何类。
您在问题中提供的链接是关于标准 PHP 库的自动加载的,它是不同的,并且更灵活。 spl_autoload_register() 允许您注册一堆自动加载函数,而不仅仅是一个。当您在代码中使用使用自动加载的库时,这是最有用的,因为它们的自动加载不必破坏您的或其他库的库。
如果您刚开始在小型项目上使用 OO,您可能只需要 __autoload(),但如果您想集成像 HTMLPurifier 这样的库,它确实使用 spl_autoload,google 查找 spl_autoload 文档,它们是第一个结果。
PHP5's autoload is only for loading classes on the fly. Only one autoload function can be used in your application (but see below). Read the autoload docs for details. Basically, you can define an __autoload() function that will load any file you want (or do anything you want, for that matter), containing any classes you want, when PHP tries to call a class that isn't loaded yet.
The link that you provided in your question is about the Standard PHP Library's autoload, which is different, and more flexible. spl_autoload_register() lets you register a stack of autoload functions, rather than just one. This is most useful when you're using libraries in your code that make use of autoload, because their autoload doesn't have to clobber yours or those of other libraries.
If you're just starting out with OO on small projects, you probably just want __autoload(), but if you want to integrate libraries like HTMLPurifier, which does use spl_autoload, google for spl_autoload for the docs, they're the first results.