Encontré este paquete PECL llamado hilos , pero aún no hay una versión. Y no aparece nada en el sitio web de PHP.
Encontré este paquete PECL llamado hilos , pero aún no hay una versión. Y no aparece nada en el sitio web de PHP.
Respuestas:
No hay nada disponible que yo sepa. Lo siguiente sería simplemente hacer que un script ejecute otro a través de CLI, pero eso es un poco rudimentario. Dependiendo de lo que esté tratando de hacer y de lo complejo que sea, esto puede o no ser una opción.
Del manual de PHP para la extensión pthreads :
pthreads es una API orientada a objetos que permite múltiples subprocesos en PHP. Incluye todas las herramientas que necesita para crear aplicaciones multiproceso dirigidas a la Web o la Consola. Las aplicaciones PHP pueden crear, leer, escribir, ejecutar y sincronizar con subprocesos, trabajadores y apilables.
Por increíble que parezca, es completamente cierto. Hoy, PHP puede realizar múltiples subprocesos para aquellos que deseen probarlo.
La primera versión de PHP4, el 22 de mayo de 2000, PHP se envió con una arquitectura segura para subprocesos, una forma de ejecutar múltiples instancias de su intérprete en subprocesos separados en entornos SAPI (API de servidor) de subprocesos múltiples. En los últimos 13 años, el diseño de esta arquitectura se ha mantenido y avanzado: desde entonces se ha utilizado en producción en los sitios web más grandes del mundo.
Subprocesos en la tierra de los usuarios nunca fue una preocupación para el equipo de PHP, y sigue siendo así hoy en día. Debe comprender que en el mundo donde PHP hace negocios, ya existe un método definido de escalado: agregar hardware. Durante los muchos años que ha existido PHP, el hardware se ha vuelto cada vez más barato y, por lo tanto, esto se convirtió cada vez menos en una preocupación para el equipo de PHP. Mientras se hacía más barato, también se volvía mucho más poderoso; Hoy en día, nuestros teléfonos móviles y tabletas tienen arquitecturas de doble y cuádruple núcleo y mucha RAM, nuestros equipos de escritorio y servidores comúnmente tienen 8 o 16 núcleos, 16 y 32 gigabytes de RAM, aunque es posible que no siempre podamos tener dos dentro del presupuesto y tener dos escritorios rara vez es útil para la mayoría de nosotros.
Además, PHP fue escrito para el no programador, es la lengua nativa de muchos aficionados. La razón por la que PHP se adopta tan fácilmente es porque es un lenguaje fácil de aprender y escribir. La razón por la que PHP es tan confiable hoy es por la gran cantidad de trabajo que implica su diseño y cada decisión tomada por el grupo PHP. Su confiabilidad y grandeza lo mantienen en el punto de mira, después de todos estos años; donde sus rivales han caído en el tiempo o la presión.
La programación de subprocesos múltiples no es fácil para la mayoría, incluso con la API más coherente y confiable, hay diferentes cosas en las que pensar y muchos conceptos erróneos. El grupo PHP no desea que los usuarios de múltiples subprocesos sean una característica central, nunca se le ha prestado mucha atención, y con razón. PHP no debería ser complejo, para todos.
A fin de cuentas, todavía hay beneficios al permitir que PHP utilice sus características listas para producción y probadas para permitir un medio de aprovechar al máximo lo que tenemos, cuando agregar más no siempre es una opción, y por mucho de tareas nunca es realmente necesario.
pthreads logra, para aquellos que desean explorarlo, una API que permite a un usuario realizar múltiples aplicaciones PHP. Su API es en gran medida un trabajo en progreso y designó un nivel beta de estabilidad e integridad.
Es de conocimiento común que algunas de las bibliotecas que usa PHP no son seguras para subprocesos, debe quedar claro para el programador que pthreads no puede cambiar esto y no intenta intentarlo. Sin embargo, cualquier biblioteca que sea segura para subprocesos puede usarse, como en cualquier otra configuración segura para subprocesos del intérprete.
pthreads utiliza hilos Posix (incluso en Windows), lo que el programador crea son hilos reales de ejecución, pero para que esos hilos sean útiles, deben tener en cuenta PHP: capaz de ejecutar código de usuario, compartir variables y permitir un medio útil de comunicación (sincronización). Por lo tanto, cada subproceso se crea con una instancia del intérprete, pero por diseño, su intérprete está aislado de todas las demás instancias del intérprete, al igual que los entornos de API de servidor multiproceso. pthreads intenta cerrar la brecha de una manera sana y segura. Muchas de las preocupaciones del programador de subprocesos en C simplemente no están ahí para el programador de pthreads, por diseño, pthreads es copiar al leer y copiar al escribir (la RAM es barata), por lo que no hay dos instancias que manipulen los mismos datos físicos. , pero ambos pueden afectar los datos en otro hilo.
Por qué copiar al leer y copiar al escribir:
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1) Mientras se mantiene un bloqueo de lectura y escritura en el almacén de datos del objeto pthreads, los datos se copian desde su ubicación original en la memoria al almacén de objetos. pthreads no ajusta el recuento de la variable, Zend puede liberar los datos originales si no hay más referencias a ella.
(2) El argumento de someOperation hace referencia al almacén de objetos, los datos originales almacenados, que en sí mismos son una copia del resultado de (1), se copian nuevamente para el motor en un contenedor zval, mientras esto ocurre, se mantiene un bloqueo de lectura en el almacén de objetos, se libera el bloqueo y el motor puede ejecutar la función. Cuando se crea el zval, tiene un recuento de 0, lo que permite que el motor libere la copia al finalizar la operación, porque no existen otras referencias a él.
(3) El último argumento para preg_match hace referencia al almacén de datos, se obtiene un bloqueo de lectura, los datos establecidos en (1) se copian a un zval, nuevamente con un recuento de 0. El bloqueo se libera, la llamada a preg_match funciona una copia de datos, que es en sí misma una copia de los datos originales.
Cosas que saber:
La tabla hash de la tienda de objetos donde se almacenan los datos, segura para subprocesos, se
basa en TsHashTable enviado con PHP por Zend.
El almacén de objetos tiene un bloqueo de lectura y escritura, se proporciona un bloqueo de acceso adicional para TsHashTable, de modo que si es necesario (y lo hace, var_dump / print_r, acceso directo a las propiedades como el motor PHP quiere hacer referencia a ellos) pthreads pueden manipular TsHashTable fuera de la API definida.
Los bloqueos solo se mantienen mientras se realizan las operaciones de copia, cuando se han realizado las copias, los bloqueos se liberan, en un orden razonable.
Esto significa:
Cuando se produce una escritura, no solo se mantiene un bloqueo de lectura y escritura, sino un bloqueo de acceso adicional. La tabla en sí está bloqueada, no hay forma posible de que otro contexto pueda bloquearla, leerla, escribirla o afectarla.
Cuando se produce una lectura, no solo se mantiene el bloqueo de lectura, sino también el bloqueo de acceso adicional, nuevamente la tabla se bloquea.
No hay dos contextos que puedan acceder física o simultáneamente a los mismos datos del almacén de objetos, pero las escrituras hechas en cualquier contexto con una referencia afectarán los datos leídos en cualquier contexto con una referencia.
Esta arquitectura no comparte nada y la única forma de existir es coexistir. Aquellos un poco conocedores verán que hay muchas copias aquí, y se preguntarán si eso es algo bueno. Se realiza una gran cantidad de copias dentro de un tiempo de ejecución dinámico, esa es la dinámica de un lenguaje dinámico. pthreads se implementa a nivel del objeto, porque se puede obtener un buen control sobre un objeto, pero los métodos, el código que ejecuta el programador, tienen otro contexto, libre de bloqueos y copias, el alcance del método local. El alcance del objeto en el caso de un objeto pthreads debe tratarse como una forma de compartir datos entre contextos, ese es su propósito. Con esto en mente, puede adoptar técnicas para evitar bloquear el almacén de objetos a menos que sea necesario,
La mayoría de las bibliotecas y extensiones disponibles para PHP son envoltorios delgados de terceros, la funcionalidad básica de PHP en cierta medida es lo mismo. pthreads no es una envoltura delgada alrededor de los hilos Posix; Es una API de subprocesos basada en subprocesos Posix. No tiene sentido implementar Threads en PHP que los usuarios no entiendan o no puedan usar. No hay razón para que una persona sin conocimiento de lo que es o no sea un mutex no debería poder aprovechar todo lo que tiene, tanto en términos de habilidad como de recursos. Un objeto funciona como un objeto, pero donde dos contextos chocarían, pthreads proporciona estabilidad y seguridad.
Cualquiera que haya trabajado en Java verá las similitudes entre un objeto pthreads y threading en Java, esas mismas personas sin duda habrán visto un error llamado ConcurrentModificationException, ya que suena un error provocado por el tiempo de ejecución de Java si dos hilos escriben los mismos datos físicos concurrentemente Entiendo por qué existe, pero me desconcierta que con recursos tan baratos como son, junto con el hecho de que el tiempo de ejecución puede detectar la concurrencia en el momento exacto y único en que se puede lograr la seguridad para el usuario, que elige lanzar un error posiblemente fatal en tiempo de ejecución en lugar de administrar la ejecución y el acceso a los datos.
No se emitirán tales errores estúpidos por pthreads, la API está escrita para hacer que el subproceso sea lo más estable y compatible posible, creo.
Multi-threading no es como usar una nueva base de datos, se debe prestar mucha atención a cada palabra en el manual y los ejemplos enviados con pthreads.
Por último, del manual de PHP:
pthreads fue, y es, un experimento con muy buenos resultados. Cualquiera de sus limitaciones o características puede cambiar en cualquier momento; Esa es la naturaleza de la experimentación. Sus limitaciones, a menudo impuestas por la implementación, existen por una buena razón; El objetivo de pthreads es proporcionar una solución útil para la multitarea en PHP a cualquier nivel. En el entorno que ejecuta pthreads, algunas restricciones y limitaciones son necesarias para proporcionar un entorno estable.
Aquí hay un ejemplo de lo que sugirió Wilco:
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
Básicamente, esto ejecuta el script PHP en la línea de comando, pero inmediatamente devuelve el PID y luego se ejecuta en segundo plano. (El echo $! Asegura que no se devuelva nada más que el PID). Esto permite que su script PHP continúe o se cierre si lo desea. Cuando utilicé esto, redirigí al usuario a otra página, donde cada 5 a 60 segundos se realiza una llamada AJAX para verificar si el informe aún se está ejecutando. (Tengo una tabla para almacenar el gen_id y el usuario con el que está relacionado). El script de verificación ejecuta lo siguiente:
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
Hay una breve publicación sobre esta técnica aquí: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
En resumen: sí, hay múltiples subprocesos en php, pero debería usar multiprocesamiento en su lugar.
Siempre hay un poco de confusión sobre la distinción de hilos y procesos, por lo que describiré brevemente ambos:
Puede lograr la computación paralela creando nuevos procesos (que también contienen un nuevo hilo) con php. Si sus hilos no necesitan mucha comunicación o sincronización, esta es su elección, ya que los procesos están aislados y no pueden interferir con el trabajo del otro. Incluso si uno falla, eso no le concierne a los demás. Si necesita mucha comunicación, debe seguir leyendo en "subprocesos múltiples" o, lamentablemente, considerar usar otro lenguaje de programación, porque la comunicación y sincronización entre procesos introduce mucha complejidad.
En php tienes dos formas de crear un nuevo proceso:
deje que el sistema operativo lo haga por usted : puede indicarle a su sistema operativo que cree un nuevo proceso y ejecute un nuevo (o el mismo) script PHP en él.
para linux puede usar lo siguiente o considerar la respuesta de Darryl Hein :
$cmd = 'nice php script.php 2>&1 & echo $!';
pclose(popen($cmd, 'r'));
para windows puedes usar esto:
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"';
pclose(popen($cmd, 'r'));
hágalo usted mismo con una bifurcación : php también ofrece la posibilidad de utilizar la bifurcación a través de la función pcntl_fork () . Aquí se puede encontrar un buen tutorial sobre cómo hacerlo, pero recomiendo encarecidamente no usarlo, ya que fork es un crimen contra la humanidad. y especialmente contra oop.
Con el subprocesamiento múltiple, todos sus subprocesos comparten sus recursos para que pueda comunicarse y sincronizarlos fácilmente sin mucha sobrecarga. Por otro lado, debes saber lo que estás haciendo, ya que las condiciones de carrera y los puntos muertos son fáciles de producir pero muy difíciles de depurar.
El php estándar no proporciona ningún subproceso múltiple, pero hay una extensión (experimental) que realmente lo hace: pthreads . Su documentación de API incluso llegó a php.net . Con él puedes hacer algunas cosas como puedes en lenguajes de programación reales :-) como este:
class MyThread extends Thread {
public function run(){
//do something time consuming
}
}
$t = new MyThread();
if($t->start()){
while($t->isRunning()){
echo ".";
usleep(100);
}
$t->join();
}
Para linux hay una guía de instalación aquí en stackoverflow's.
Para windows hay uno ahora:
Edite [phpDirectory] /php.ini e inserte la siguiente línea
extension=php_pthreads.dll
Pruébelo con el script anterior con un poco de sueño o algo allí donde está el comentario.
Y ahora el gran PERO : aunque esto realmente funciona, php no fue creado originalmente para multithreading. Existe una versión de php segura para subprocesos y, a partir de v5.4, parece estar casi libre de errores, pero el uso de php en un entorno multiproceso aún no se recomienda en el manual de php (pero tal vez simplemente no actualizaron su manual en esto, todavía). Un problema mucho mayor podría ser que muchas extensiones comunes no son seguras para subprocesos . Por lo tanto, es posible que obtenga hilos con esta extensión php, pero las funciones de las que depende todavía no son seguras para los hilos, por lo que probablemente encontrará condiciones de carrera, puntos muertos, etc.
Puede usar pcntl_fork () para lograr algo similar a los hilos. Técnicamente son procesos separados, por lo que la comunicación entre los dos no es tan simple con hilos, y creo que no funcionará si apache llama a PHP.
Si a alguien le importa, he revivido php_threading (no lo mismo que los subprocesos, pero similar) y en realidad lo tengo al punto donde funciona (algo) bien.
pcntl_fork()
es lo que está buscando, pero su proceso no se bifurca. entonces tendrá el problema del intercambio de datos. para resolverlos, puede usar las colas de mensajes de las funciones de semáforo phps ( http://www.php.net/manual/de/ref.sem.php ) pueden ser un poco más fáciles al principio que los segmentos de memoria compartida.
De todos modos, una estrategia que estoy usando en un marco web que estoy desarrollando que carga bloques de una página web que requieren muchos recursos (probablemente con solicitudes externas) en paralelo: estoy haciendo una cola de trabajo para saber qué datos estoy esperando y luego bifurco fuera de los trabajos para cada proceso. Una vez hecho esto, almacenan sus datos en el caché de la APC bajo una clave única a la que puede acceder el proceso principal. Una vez que todos los datos están allí, continúan. Estoy usando simpleusleep()
para esperar porque la comunicación entre procesos no es posible en apache (los niños perderán la conexión con sus padres y se convertirán en zombies ...). así que esto me lleva a lo último: ¡es importante auto matar a cada niño! también hay clases que bifurcan procesos pero conservan datos, no los examiné, pero zend framework tiene uno, y generalmente hacen un código lento pero confiable. Lo puedes encontrar aquí:
http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html ¡
Creo que usan segmentos shm! bueno, por último, pero no menos importante, hay un error en este sitio web zend, un error menor en el ejemplo.
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}
Hay una extensión de subprocesos que se está desarrollando de manera activa basada en PThreads que se ve muy prometedora en https://github.com/krakjoe/pthreads
Solo una actualización, parece que los chicos de PHP están trabajando en el subproceso de soporte y está disponible ahora.
Aquí está el enlace: http://php.net/manual/en/book.pthreads.php
Tengo una clase de subprocesamiento de PHP que se ha ejecutado sin problemas en un entorno de producción durante más de dos años.
EDITAR: ahora está disponible como una biblioteca de compositores y como parte de mi marco MVC, Hazaar MVC.
Sé que esta es una pregunta muy antigua, pero podría consultar http://phpthreadlib.sourceforge.net/
Comunicación bidireccional, soporte para Win32 y no se requieren extensiones.
¿Has oído hablar appserver
de TechDivision?
Está escrito en php y funciona como un servidor de aplicaciones que administra subprocesos múltiples para aplicaciones php de alto tráfico. Todavía está en beta pero es muy prometedor.
Existe la característica bastante oscura, y que pronto será desaprobada, llamada ticks . Para lo único que lo he usado es para permitir que un script capture SIGKILL (Ctrl + C) y se cierre con gracia.
pcntl_fork()
) funcionará si se llama desde Apache?