Q:

Time it takes to assign a variable vs. assign + add

<?php

$a = microtime(true);
$num = 0;
for($i=0;$i<10000000;$i++)
{
$num = $i;
}

$b= microtime(true);

echo $b-$a;
?>

I run this on Ubuntu 12.10 and Apache 2
will give me approx. .50 seconds... when I run an assignment for a million times.. BUT BUT... 
the same code, instead of $num = $i ... i go ... 
$num = $i + 10; and it now takes almost 1.5 times less time to execute.. around .36 consistently.. 
How come the simple assignment is taking more, whilst an assignment and adding a 10 over it... takes less time!

A:

This is just an educated guess, based on looking at the latest php source on Github, but I'd say this difference is due to function call overhead in the interpreter source.

$tmp = $i;

compiles to a single opcode ASSIGN !2, !1;, which copies one named variable's value to another named variable. In the source, the key part looks like this:
if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
    /* nothing to destroy */
    ZVAL_COPY_VALUE(variable_ptr, value);
    zendi_zval_copy_ctor(*variable_ptr);
}

$tmp = $i + 10;

compiles to two opcodes ADD ~8 !1, 10; ASSIGN !2, ~8;, which creates a temporary variable ~8 and assigns its value to a named variable. In the source, the key part looks like this:
if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
    /* nothing to destroy */
    ZVAL_COPY_VALUE(variable_ptr, value);
}

Notice that there's an extra function call to zendi_zval_copy_ctor() in the first case. That function performs some bookkeeping as needed (e.g. if the original variable is a resource, it needs to make sure that resource is not freed until this new variable is gone, etc.). For a primitive type such as a number, there's nothing to do, but the function call itself introduces some overhead, which accumulates over 10 million iterations of your test. You should note that this overhead is normally negligible, because even in 10 million iterations it only accumulated to .14 seconds.

@Kolink's observation about a constant being faster can also be answered in the same function. It includes a check to avoid redundant copying if the new value is the same as the old one:
if (EXPECTED(variable_ptr != value)) {
copy_value:
    // the same code that handles `$tmp = $i` above
    if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
        /* nothing to destroy */
        ZVAL_COPY_VALUE(variable_ptr, value);
        zendi_zval_copy_ctor(*variable_ptr);
    } else {
        /* irrelevant to the question */
    }
}

So only the first assignment of $tmp = $x copies the value of $x, the following ones see that the value of $tmp would not change and skip the copying, making it faster.

