Pergunta

Em PHP, parâmetros de função podem ser passados ??por referência, antecedendo um e comercial para o parâmetro na declaração da função, assim:

function foo(&$bar)
{
    // ...
}

Agora, estou ciente de que este é não projetado para melhorar o desempenho, mas para permitir que funções para variáveis ??de mudança que normalmente estão fora do seu âmbito.

Em vez disso, PHP parece usar cópia na escrita para evitar objetos copiando (e talvez também matrizes) até que sejam alteradas. Assim, para funções que não mudam seus parâmetros, o efeito deve ser o mesmo como se você tivesse passado por referência.

No entanto, eu queria saber se a escrever a lógica de cópia Em talvez seja curto-circuitados na passagem por referência e se isso tem algum impacto no desempenho.

ETA: Para ter certeza, eu supor que não mais rápido é, e estou bem ciente de que não é isso que as referências são para. Então eu acho que minhas próprias suposições são bastante bom, eu estou apenas procurando por uma resposta de alguém que realmente sabe o que está definitivamente acontecendo sob o capô. Em cinco anos de desenvolvimento PHP, eu sempre achei que é difícil obter informações sobre a qualidade internos PHP curto de ler a fonte.

Foi útil?

Solução

Os usos Zend Engine copiar-on-write, e quando você usa uma referência a si mesmo, ele incorre em uma pequena sobrecarga extra. só pode encontrar esta menção no momento da escrita, porém, e comentários no os manuais conter outros links.

(EDIT) A página de manual sobre objetos e referências contém um pouco mais de informação sobre como variáveis ??de objeto diferem das referências.

Outras dicas

Em um teste com 100 000 iterações de chamar uma função com uma seqüência de 20 kB, os resultados são:

Função que apenas lê / utiliza o parâmetro

pass by value:      0.12065005 seconds
pass by reference:  1.52171397 seconds

Função para escrever / alterar o parâmetro

pass by value:      1.52223396 seconds
pass by reference:  1.52388787 seconds

Conclusões

  1. Passe o parâmetro por valor é sempre mais rápido

  2. Se a alteração da função do valor da variável transmitida, para fins práticos é o mesmo que passe por referência do que pelo valor

Eu corri alguns testes sobre isso porque eu não tinha certeza das respostas dadas.

Os meus resultados mostram que passar grandes matrizes ou seqüências por referência é significativamente mais rápida.

Aqui estão meus resultados: benchmark

O eixo Y (Corridas) é quantas vezes uma função poderia ser chamado em 1 segundo * 10

O teste foi repetido 8 vezes para cada função / variável

E aqui está as variáveis ??que eu usei:

$large_array = array_fill(PHP_INT_MAX / 2, 1000, 'a');
$small_array = array('this', 'is', 'a', 'small', 'array');
$large_object = (object)$large_array;
$large_string = str_repeat('a', 100000);
$small_string = 'this is a small string';
$value = PHP_INT_MAX / 2;

Estas são as funções:

function pass_by_ref(&$var) {
}

function pass_by_val($var) {
}

Eu experimentei com valores e referências de 10k seqüência de bytes passá-la para duas funções idênticas. Uma leva argumento por valor e a segunda por referência. Eram funções comuns - tomar argumento, fazer o processamento simples e retorna um valor. Eu fiz 100 000 chamadas de ambos e descobriu que as referências não são projetados para aumentar o desempenho - lucro de referência estava perto de 4-5% e cresce somente quando corda torna-se grande o suficiente (100k e por mais tempo, que deu% de melhoria 6-7) . Então, minha conclusão é não usar referências para aumentar a perfomance, este material não é para isso.

Eu usei PHP Versão 5.3.1

Eu tenho certeza que não, não mais rápido é. Além disso, ele diz especificamente no manual para não tentar usar referências para aumentar o desempenho.

Edit: Não é possível localizar onde diz que, mas está lá

!

Não há nada melhor do que um pedaço teste de código

<?PHP
$r = array();

for($i=0; $i<500;$i++){
$r[]=5;
}

function a($r){
$r[0]=1;
}
function b(&$r){
$r[0]=1;
}

$start = microtime(true);
for($i=0;$i<9999;$i++){
  //a($r);
  b($r);
}
$end = microtime(true);

echo $end-$start;
?>

O resultado final! Quanto maior for a matriz (ou quanto maior for a contagem de chamadas), quanto maior a diferença. Portanto, neste caso, chamando por referência é mais rápido porque o valor é alterado dentro da função.

Caso contrário, não há diferença real entre "por referência" e "por valor", o compilador é inteligente o suficiente para não criar uma nova cópia de cada vez, se não houver necessidade.

Eu tentei referência isto com um exemplo do mundo real com base em um projeto que eu estava trabalhando. Como sempre, as diferenças são triviais, mas os resultados foram um tanto inesperado. Para a maioria dos benchmarks que eu vi, a função chamada não altera realmente o valor passado. Eu executei um str_replace () simples sobre ela.

**Pass by Value Test Code:**

$originalString=''; // 1000 pseudo-random digits

function replace($string) {
    return str_replace('1', 'x',$string);
}
$output = '';
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);

for ($i = 0; $i < 10; $i++ ) {
    for ($j = 0; $j < 1000000; $j++) {
        $string = $originalString;
        $string = replace($string);
    }
}

/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "\n" . 'Total Time' .
    ': ' . $totalTime;
$output .= "\n" . $string;
echo $output;

passar por referência Código Teste

O mesmo, exceto para

function replace(&$string) {
    $string = str_replace('1', 'x',$string);
}
/* ... */
replace($string);

Resultados em segundos (10 milhões de iterações):

PHP 5
    Value:     14.1007
    Reference: 11.5564

PHP 7
    Value:     3.0799
    Reference: 2.9489

A diferença é uma fracção de um milissegundo por chamada de função, mas para este caso de utilização, passando por referência é mais rápido em ambos PHP 5 e PHP 7.

(Nota: os testes PHP 7 foram realizados em uma máquina mais rápida - PHP 7 é mais rápido, mas provavelmente não muito mais rápido.)

É simples, não há necessidade de teste de qualquer coisa. Depende do caso de uso.

passagem por valor será sempre mais rápido, valor que a referência para a pequena quantidade de argumentos. Isso depende de quantas variáveis ??que a arquitetura permite a serem passados ??através de registos (ABI).

Por exemplo x64 permitirá que você 4 valores de 64 bits cada um para ser passada através de registos. https://en.wikipedia.org/wiki/X86_calling_conventions

Isso é porque você não tem que de-referentiate os ponteiros, basta usar o valor diretamente.

Se os dados que precisa ser passado é maior do que ABI, resto de valores vai para empilhar. Neste caso, uma matriz ou um objecto (que por exemplo é de uma classe, ou uma estrutura de cabeçalhos +) será sempre mais rápido, REFERÊNCIA.

Isso ocorre porque uma referência é apenas um ponteiro para os dados (não dados em si), tamanho fixo, digamos, 32 ou 64 bits, dependendo da máquina. Esse ponteiro vai caber em um registo da CPU.

PHP é escrito em C / C ++ para que eu esperaria se comportam da mesma.

Não há necessidade de adicionar & operador ao passar objetos. Em PHP 5+ objetos são passados ??por referência de qualquer maneira.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top