【问题标题】:Memory usage in static vs instance methods静态与实例方法中的内存使用情况
【发布时间】:2018-01-20 20:13:35
【问题描述】:

我已经制作了自己的 php 迷你框架,我的 index.php 看起来像这样

<?php
    require __DIR__.'/../app/autoloader.php';
    Autoloader::register();

    use Stories\http\routing\{RouteCollection,Matcher,Route};
    use Stories\http\Request;
    use Stories\App\Stories;

    $app = new Stories();
    $routes = new RouteCollection();

    $home  = new Route('/',function(Request $request) use ($app) {
        return \Stories\Processor::home($request,$app);
    }, ['method' => 'GET']);
    $routes->add("home",$home);

    ...

     $login = new Route('/login', function (Request $request) use ($app) {
        return \Stories\Processor::login($request,$app);
    }, ['method' => 'GET']);
    $routes->add('login',$login);

    $matcher = new Matcher($routes);
    $matcher->find()->run();

但是,有些人告诉我,创建一个\my\namespace\processor 的实例并将其传递给这样的函数:

<?php
    require __DIR__.'/../app/autoloader.php';
    Autoloader::register();

    use Stories\http\routing\{RouteCollection,Matcher,Route};
    use Stories\http\Request;
    use Stories\App\Stories;
    use Stories\Processor;

    $app = new Stories();
    $routes = new RouteCollection();
    $processor = new Processor();

    $home  = new Route('/',function(Request $request) use ($app,$processor) {
        return $processor->home($request,$app);
    }, ['method' => 'GET']);
    $routes->add("home",$home);

    ...

     $login = new Route('/login', function (Request $request) use ($app,$processor) {
        return $processor->login($request,$app);
    }, ['method' => 'GET']);
    $routes->add('login',$login);

    $matcher = new Matcher($routes);
    $matcher->find()->run();

会更好,因为已经创建了类实例,但我不知道为什么,我的路由器不运行任何功能,而只运行与 URI 匹配的功能,所以我认为这不会成为问题.两种方法我都测试过了,没有发现任何区别。

由于我是一名高中生,并且告诉我这是大学老师的人之一,我认为他可能是对的,但我认为内存使用没有任何差异。

更新

根据@smuuf 的回答,我想说processor 不是一个合适的类,而不是在index.php 中的每个函数内编写10 或20 行代码调用其他类,如view,users ,orm... 等等,我使用静态方法创建了 processor 类,它们的作用完全相同,processor 类在处理请求时不使用任何自己的方法或属性。

更新 2

我刚刚更新了我的路由器,我还更新了代码,使其看起来与我的 index.php 完全一样,但我仍在寻找相同问题的答案。

【问题讨论】:

  • 拥有一个最终具有与非静态对应物的单个实例相同的成员的静态对象将占用相同的内存。我不是 100% 确定 PHP 是否这样做,但其他语言基本上每个类都有一个特殊的实例来保存静态成员,所以基本上你创建一个单例或使用静态内存使用是相同的。区别在于可测试性。如果您使用静态测试会困难得多,但这可能不是您在学校所关心的问题。
  • 我们在学校都没有学过php,我是自学的,谢谢你的评论
  • @apokryfos 你能解释一下你对可测试性差异的评论吗?我发现静态方法更容易测试,因为它们始终是自包含的,因此无需设置任何类变量或担心状态。
  • @BobRay 在test doubles 的 phpunit 页面中有更多详细信息,但长话短说,如果您正在测试一个依赖于另一个单元的单元,那么您通常会模拟另一个单元以隔离您的测试,但是大多数测试框架不会模拟静态,只会创建模拟类实例。

标签: php memory


【解决方案1】:

简答: 没关系。


更长的答案:如果该实例是不必要地创建的,那么传递一个实例本质上没有什么更好。看,这一切都归结为你的 processor 真正做了什么

  1. 如果processor 确实是一些复杂的处理组件,需要在对其方法的调用之间保持一些内部状态,或者共享一些资源(例如数据库连接),那么是的,这是一个“正确的类”,绝对应该被实例化。

  2. 如果您的processor 真的只是一个“相关(或不相关)函数的集合”,其中(例如) 每个方法处理不同的您的应用程序中的 URL(如您的示例)实例不需要处理一些内部状态,它的方法将' 不共享任何资源(例如数据库连接),确实无需为此创建实例

事实上,如果我写了这样的“帮助器/函数集合类”,我会明确地限制实例化:

  • __construct 方法指定为private,或
  • 将整个类定义为abstract class

最终,这更多地是关于您希望如何组织代码。 内存使用差异 - 在这种情况下 - 可以忽略不计。


在我看来(严格来说):使用静态方法确实需要更少的内存并且会稍微快一些,因为没有人需要在调用它的方法之前处理类的实例化。然而,这种性能差异在 99% 的情况下在实际应用中并不明显。

【讨论】:

  • processor 类不是正确的类,但它调用其他正确的类,而不是在 index.php 中的每个函数中编写 10 行代码,我决定将进程留在静态方法中在processor 中,这有什么不同吗?
  • 在我看到你的完整代码之前,我真的无法判断,但在这种情况下,我认为它不会。
  • 如果一个类只包含静态方法而没有类变量,那么实例化的类对象使用的内存量是否与“包含”该类所需的内存量大致相同,所以你可以调用它的静态方法?
猜你喜欢
  • 2011-01-21
  • 1970-01-01
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
  • 2015-06-22
相关资源
最近更新 更多