6

You can see two simplified snippets below that don't vary in their outcome.

Pattern 1, objects from scratch:

foreach ($recipients as $recipient) {
    $message = new Message();
    $message->setBody("This is the body of the message.");
    $message->setRecipient($recipient);

    $transport->sendMessage($message);
    $persister->saveToDatabase($message); // Updated line
    unset($message);
}

Pattern 2, cloning a prototype object:

$prototype = new Message();
$prototype->setBody("This is the body of the message.");

foreach ($recipients as $recipient) {
    $message = clone $prototype;
    $message->setRecipient($recipient);

    $transport->sendMessage($message);
    $persister->saveToDatabase($message); // Updated line
    unset($message);
}
unset($prototype);

Does the object cloning (pattern 2) provide performance improvements over creating objects from scratch (pattern 1) in terms of memory usage, garbage collection and/or CPU cycles? Consider also high number of fixed properties (that do not change between the instances) and high number of loops.


Update: I need different object instances in each loop. I added saveToDatabase call to the examples to resemble that, let it for example give an ID to the message. ;)

TechWisdom
  • 3,960
  • 4
  • 33
  • 40
Ville Mattila
  • 1,343
  • 3
  • 15
  • 28

2 Answers2

4

Looks like someone has helped you with your code, but for the benefit of others visiting the question, here's the answer to what is asked in the title:

Usually. The new keyword causes the __construct() magic method to run; the clone keyword causes the __clone() magic method to run.

The point of the Prototype Pattern is to avoid rerunning an expensive constructor repeatedly, especially when the end result (in terms of the internal state of the objects) is the same each time.

The Prototype Pattern is only normally used where there is a significant performance problem that needs to be addressed, not just if you need a lot of objects.

Sam Burns
  • 480
  • 3
  • 13
0

In your case, object cloning is not necessary.

Look at this:

$message = new Message();
$message->setBody("This is the body of the message.");

foreach ($recipients as $recipient) {
    $message->setRecipient($recipient);
    $transport->sendMessage($message);
}

This should use the least memory. And you can't destroy an object. Let the GC do it for you.

I'm not sure if manually unsetting is necessary..

Best way to destroy PHP object?

What's better at freeing memory with PHP: unset() or $var = null

In terms of memory usage cloning should be the same as new object since every property is copied. But cloning is slightly faster. Look at this benchmark.

Community
  • 1
  • 1
bitWorking
  • 12,485
  • 1
  • 32
  • 38
  • Thanks for your answer. In my case, two different instances are required. I updated my question to better reflect this requirement. But I think your reference to the `clone` benchmark will answer my question pretty well: better to clone than create new objects. – Ville Mattila Jul 13 '13 at 14:21
  • Clone doesn't need to look for a constructor and execute it. The heavier the constructor, the bigger the benefit. – tacone Nov 18 '14 at 14:33
  • @tacone It does have to look for a magic __clone() though, so it's only the execution part which varies, and all depends on the class. – IMSoP Jul 27 '15 at 21:46