【问题标题】:PHP: Performance: splat operator or reflectionPHP:性能:splat 运算符或反射
【发布时间】:2014-08-29 07:50:49
【问题描述】:

在我正在创建的应用程序中,我需要将未知数量的参数传递给类的未知构造函数。 类(+ 命名空间)是一个字符串,在 $class 中。 参数在一个数组中。

这个应用程序将在几个月内部署,所以我们认为我们可以在 PHP 5.6 中开发它。 所以我认为这个问题的解决方案是:

$instance = new $class(...$args);

这是有效的......

但是我的同事不愿意接受这个,因为CI服务器不理解这行代码。 他们的解决方案是:

$reflect = new \ReflectionClass($class);
$instance = $reflect->newInstanceArgs($args)

现在:两者都工作正常,所以这不是问题。 但我的想法是反射比使用其他方式(如 PHP 5.6 splat 运算符)要慢。

还有一个问题:反射是一种好方法吗,我应该从 CI 服务器理解该行的那一刻起使用 splat 运算符吗?

【问题讨论】:

  • 以任何一种方式对其进行基准测试。如果您发现任何显着差异,请给我们写明信片。
  • 未知类?这听起来像是一个非常糟糕的设计。
  • 为什么不使用一个变量作为参数数组?
  • 未知类:在那个级别我只确定它是一个实现接口的类。我使用的方法是将数据从一个数据源转换为数据类。对于方法本身,类是未知的,因为它是抽象的。

标签: php php-5.6


【解决方案1】:

肯定会选择 splat 运算符,为什么?它比反射方法快得多(我正在使用它并且实现似乎非常好)。反射也破坏了与设计有关的任何事物,例如,它允许您破坏封装。

PS:不是$instance = new $class(...$args);吗?

【讨论】:

  • 是的,是我的错字,这是正确的代码。
  • 快得多并不是一个好的指标。您能否将您的基准与您的发现一起发布。
【解决方案2】:

今天我有时间对其进行基准测试。
就像我预期的那样(和 Fleshgrinder 说的):splat 运算符更快。

基准时间:
反射:11.686084032059s
splat:6.8125338554382s

差不多有一半的时间了……这很严重……

基准测试(通过http://codepad.org/jqOQkaZR):

<?php

require "autoload.php";

function convertStdToCollectionReflection(array $stds, $entity, $initVars)
{
    $records = array();
    $class = $entity . '\\Entity';
    foreach ($stds as $record) {
        $args = array();
        foreach ($initVars as $var) {
            $args[] = $record->$var;
        }
        $reflect = new \ReflectionClass($class);
        $records[] = $reflect->newInstanceArgs($args);
    }

    return $records;
}

function convertStdToCollectionSplat(array $stds, $entity, $initVars)
{
    $records = array();
    $class = $entity . '\\Entity';
    foreach ($stds as $record) {
        $args = array();
        foreach ($initVars as $var) {
            $args[] = $record->$var;
        }
        $records[] = new $class(...$args);
    }

    return $records;
}

$dummyObject = array();
for ($i = 0; $i < 10; $i++) {
    $dummyclass = new \stdClass();
    $dummyclass->id = $i;
    $dummyclass->description = 'Just a number... ' . $i;
    $dummyObject[] = $dummyclass;
}

print 'Start Reflection test' . PHP_EOL;
$reflectionStart = microtime(true);

for($i = 0; $i < 1000000; $i++) {
    convertStdToCollectionReflection(
        $dummyObject,
        'Xcs\Core\Record',
        array(
            'id',
            'description'
        )
    );
}

$reflectionEnd = microtime(true);

print 'Start Splat test' . PHP_EOL;
$splatStart = microtime(true);

for($i = 0; $i < 1000000; $i++) {
    convertStdToCollectionSplat(
        $dummyObject,
        'Xcs\Core\Record',
        array(
            'id',
            'description'
        )
    );
}

$splatEnd = microtime(true);

print PHP_EOL . 'OUTPUT:' . PHP_EOL;
print 'Reflection: ' . ($reflectionEnd - $reflectionStart) . 's' . PHP_EOL;
print 'Splat: ' . ($splatEnd - $splatStart) . 's' . PHP_EOL;

【讨论】:

  • 你能发布你的基准吗?否则你的回答是没有用的。
  • 这很简单,只是对两种实现都做同样的工作。 codepad.org/jqOQkaZR
  • 我并不是说这很难:-)。我刚刚告诉过,如果没有产生这些结果的代码,结果本身是没有用的。 +1 代码。
猜你喜欢
  • 2012-02-08
  • 2013-07-04
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
  • 2015-12-11
  • 2015-03-13
相关资源
最近更新 更多