لماذا تكون طريقة __set() الفارغة أبطأ من الطريقة التي تعمل؟

StackOverflow https://stackoverflow.com//questions/23050278

سؤال

كنت أتلاعب بأساليب PHP السحرية (على وجه التحديد التحميل الزائد على الممتلكات)، وأثناء إجراء المقارنة المعيارية الدقيقة، واجهت مشكلة أواجه صعوبة في شرحها:

ويبدو أن أ __set تستغرق الطريقة ذات النص الفارغ وقتًا أطول للتشغيل من الطريقة التي تعمل.يوضح مقتطف الكود أدناه هذا:

class EmptySetter {
    public function __set($name, $value) {}
}

class NonEmptySetter {
    public function __set($name, $value) {
        $this->{$name} = $value;
    }
}

function benchmark($obj) {
    $start_time = microtime(TRUE);
    for ($i = 0; $i < 10000000; $i++) {
        $obj->foo = 42;
    }
    return microtime(TRUE) - $start_time;
}

printf("EmptySetter: %.2f seconds\n", benchmark(new EmptySetter));
printf("NonEmptySetter: %.2f seconds\n", benchmark(new NonEmptySetter));

// output (on my Core 2 Duo laptop):
// EmptySetter: 4.39 seconds
// NonEmptySetter: 1.28 seconds

هل لدى أي شخص تفسير لماذا يحدث هذا؟

هل كانت مفيدة؟

المحلول

أوه، أرى أنها حالة اختبار خاطئة.

بعد الحلقة الأولى NonEmptySetter سيكون لديه ممتلكات عامة جديدة foo.الحلقات التالية لا تتصل __set الطريقة على الإطلاق، يستخدمون الملكية العامة.

class NonEmptySetter {
    public function __set($name, $value) {
        echo 'called only once'; // would be echoed only once.
        $this->{$name} = $value;
    }
}

اختبار صالح

class EmptySetter {
    public function __set($name, $value) {}
}

class NonEmptySetter {
    public function __set($name, $value) {
        $this->{$name} = $value;
    }
}

function benchmark($class_name) {
    $start_time = microtime(TRUE);
    for ($i = 0; $i < 1000000; $i++) {
        $obj = new $class_name();
        $obj->foo = 42;
    }
    return microtime(TRUE) - $start_time;
}

printf("NonEmptySetter: %.2f seconds\n", benchmark('NonEmptySetter'));
printf("EmptySetter: %.2f seconds\n", benchmark('EmptySetter'));

http://3v4l.org/gVtSq

أداة الضبط الفارغة أسرع.

نصائح أخرى

لا يمكنك المقارنة بين هذين، لأن النتيجة النهائية ليست متساوية.

$o1 = (new NonEmptySetter);
$o1->foo = 42;

$o2 = (new EmptySetter);
$o2->foo = 42;

var_dump($o1, $o2, $o2->foo);

هذا يعطي:

object(NonEmptySetter)[1]
  public 'foo' => int 42

object(EmptySetter)[2]

null

بالإضافة إلى ملاحظة للأخيرة: Notice: Undefined property: EmptySetter::$foo

وهذا يعني لم يتم تعيين الخاصية أبدًا, ، إنه غير موجود، أيها الغبار الخيالي، أفترض أن المخالفات هناك تستغرق وقتًا.

enter image description here

إذا أعلنت صفك بشكل صحيح (لاحظ $foo):

class EmptySetter {
    public $foo = NULL;
    public function __set($name, $value) {}
}

سيتم ربط المواعيد: تم الإعلان عن المعيار الخاص بك مع EmptySetter::$foo

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top