2011-05-23 5 views
9
valor

Tengo el siguiente código simple para probar contra la colisión en una clave principal que estoy creando:PHP in_array() rendimiento horrible. fatest manera de buscar matriz para

$machine_ids = array(); 

for($i = 0; $i < 100000; $i++) { 
    //Generate machine id returns a 15 character alphanumeric string 
    $mid = Functions::generate_machine_id(); 

    if(in_array($mid, $machine_ids)) { 
     die("Collision!"); 
    } else { 
     $machine_ids[] = $mid; 
    } 
} 

die("Success!"); 

Cualquier idea de por qué esto está teniendo muchos minutos para correr? De todos modos para acelerarlo?

+5

¿Ha perfila que 'in_array' es el culpable y no 'Funciones :: generate_machine_id()'? – deceze

+0

¿Tiene el código para 'Funciones :: generate_machine_id' a mano? – cHao

Respuesta

11
for($i = 0; $i < 100000; $i++) 
{ 
    //Generate machine id returns a 15 character alphanumeric string 
    $mid = Functions::generate_machine_id(); 
    if (isset($machine_ids[$mid])) 
    { 
    die("Collision!"); 
    } 
    $machine_ids[$mid] = true; 
} 
11

Para esto, use $mid como claves, y el valor ficticio como valor. En concreto, en lugar de

if(in_array($mid, $machine_ids)) { 
    die("Collision!"); 
} else { 
    $machine_ids[] = $mid; 
} 

uso

if(isset($machine_ids[$mid])) { 
    die("Collision!"); 
} else { 
    $machine_ids[$mid] = 1; 
} 

Al final se puede extraer la matriz que originalmente quería con array_keys($machine_ids).

Esto debería ser mucho más rápido. Si todavía es lento, entonces su Functions::generate_machine_id() es lento.

EDITAR para agregar isset según los comentarios.

+2

Pásame a ello. :) Aunque deberías usar 'isset ($ machine_ids [$ mid])'. – deceze

+0

Estoy de acuerdo con engaño, y creo que 'if ($ machine_ids [$ mid])' devolverá false (no realmente una colisión) si el valor es entero 0, cadena vacía, NULL, etc. En cualquier caso, 'isset()' es el camino a seguir. Sin embargo, me acabo de dar cuenta de que OP dijo que siempre será un alphanum de 15 caracteres. –

+0

@deceze: ¿Alguna razón? ¿El rendimiento alcanzado por 'isset' es inferior al rendimiento alcanzado por la conversión implícita a booleano? ¿O es teórico, ya que en PHP '0' también es falso, que diferiría de' isset'? (en este caso, todo lo que tenemos son vacíos y unos, así que es seguro) – Amadan

3

La comprobación de la membresía de la matriz es una operación O (n), ya que tiene que comparar el valor de cada elemento en la matriz. Después de agregar un montón de cosas a la matriz, naturalmente se vuelve más lento.

Si necesita realizar un montón de pruebas de membresía, como es el caso aquí, debe usar una estructura de datos diferente que admita O (1) pruebas de membresía, como un hash.

1

refactorizar el código para que utilice una matriz asociada a sostener las ID de máquinas y utilizar isset para comprobar

if(isset($machine_id[$mid])) die("Collision"); 

$machine_ids[$mid] = $mid; 

Usando isset debe ser más rápido

Cuestiones relacionadas