Contenido

[Corregido] Ejecutando procesos en paralelo con Javascript

14 Abr

+ 14

Actualizo (08:00):

El sistema usado en el ejemplo que croczilla.com publica, está desarrollado usando Stratified Javascript (SJS), una implemenetación de Javascript con Javascript O.o. Se trata de una librería multinavegador que nos permite añadir concurrencia a Javascript fácilmente.

La clave está en el uso de tags <script /> de un tipo diferente al que conocemos como text/javascript, usando uno propio se encarga de evaluar el código contenido en él añadiendo una serie de funcionalidades como hold(),resume()suspend() y la posibilidad de usar concurrencia en Javascript.

Ejemplo

<script type="text/javascript" src="sjs-loader.js"></script>
<script type="text/sjs">
….
function animate(elemname, duration_ms, step_ms) {
 var elem = document.getElementById(elemname);
 var start_time = new Date();
 var x = 0;
 do {
 elem.style.left = x;
 x = (x + 10) % 200;
 hold(step_ms); // Parando la ejecución
 } while (duration_ms > new Date() - start_time);
 }

 function par(a, b) {
 alert("all done");
 }
 // Procesos paralelos
 par(animate("animated_element_1", 10000, 100),
 animate("animated_element_2", 7000, 80));
…
</script>

Como podemos ver, en esta porción de código sacada de una demo de crockzilla.com, usamos hold() para detender la ejecución y usamos el paso de parámetros para comenzar la concurrencia de procesos.

Con los Web Workers a la vuelta de la esquina, estas técnicas nos puedes empezar a mostrar el camino a seguir en unos meses (años). Por el momento, recomendaría usarla con precaución ya que no debemos olvidar que la librería basa su funcionamiento en la evaluación del código, con el coste que esta operación conlleva.

La presentación por parte de Apple de la «multitarea» en la próxima versión de iPhone OS 4, me ha hecho recordar un artículo que tenía por ahí perdido en el que nos mostraba un ingenioso sistema de multitarea «real» con Javascript. El enlace es algo antiguo pero realmente interesante.

He montado un ejemplo para verlo funcionando.

Código

// Tareas a realizar
function task1(){....}
function task2(){....}
function task3(){....}

// Función void
function multitask() { /* ignore args */ }

// Llamada
multitask(task1(), task2(), task3());

Básicamente el código se compone de una serie de tareas (task(x)) que se ejecutarán a la vez, y que llamaremos como si de parámetros se trataran a la función multitask().

La función multitask() es una función vacia que no realiza nada y nos permite ejecutar el código de todas las tareas en paralelo que queramos ejecutar. He hecho una prueba con 200 tareas y ha funcionado sin problemas 😀

Actualizo (12:12):

epplestun me recuerda un interesante artículo que escribió hace unos días sobre Web Workers de HTML5. Totalmente recomendable si te interesa este tema. También tenemos un artículo de John Resig sobre el tema que vimos hace un tiempo.

Actualizo (13:13):
Fallo mio, por no leer más detenidamente. El ejemplo que he montado, y que he explicado, funciona por que me baso en setTimeouts() y simula esa reacción. Pero en NINGÚN CASO se puede llamar multitarea a esto. Se trata de una implementación SJS que Venkman explica perfectamente en un comentario.

Siento todas las molestias, ilusiones y problemas causados… me emocioné y me salté ese imprescindible detalle :(.


  • Muy interesante. Me lo guardo en marcadores 😀

  • Al hilo de esto, hace unos días escribí sobre algo parecido en mi blog, sobre los Web Workers para HTML5, os lo dejo por si os interesa 🙂

    http://epplestun.blogspot.com/2010/04/web-workers-que-son-y-para-que-sirven_03.html

  • Parece que va bien, ¿no?

    Yo llevaba ya tiempo intentando pensar alguna forma de ejecutar procesos en pararlelo, pero no había caido en esto tan sencillo.

    Le daré caña a ver qué tal va con un poco de estres

    Muy buena!

  • Estás seguro de que esto funciona? que diferencia hay entre ejecutar esto:

    multitask(task1(), task2(), task3());

    y esto:

    task1(); task2(); task3();

    Un saludo!

  • Uh? ô.o

    Supongo que eres consciente de que StratifiedJS no es, en absoluto, lo que has hecho con tu ejemplo. De hecho, en tu ejemplo puedes probar a hacer los siguientes mínimos cambios y ver que se ejecuta exactamente igual:

    1. Quita la función multitask
    2. En lugar de hacer la llamada a multitask, ejecuta task1(); task2(); task3();

    ¿Cuál es el detalle? En tu ejemplo, todo se basa en el uso de los timeouts. Por eso, «funciona». El problema es que te obliga a hacer tus tasks de una forma muy muy determinada.

    Con Stratified JS ( http://croczilla.com/~alex/oni/stratified/sjs-loader.js ) lo que hace es bastante distinto. Primero porque hace lo que necesitarías para que en tu ejemplo las tasks se ejecutaran realmente en paralelo. Y eso es cambiar un mecanismo fundamental de Javascript. En Javascript (por la especificación del lenguaje) los argumentos a una llamada se evalúan de forma secuencial. Primero se evalúa task1(), luego se evalúa task2() y luego task3(). SJS cambia eso y lo que hace es que los argumentos pasados a una llamada se evalúan concurrentemente (nota 1).

    En segundo lugar porque la forma de SJS de hacer eso es cualquier cosa menos algo tan sencillo como tu ejemplo. De hecho, en lo que se basa es en extender el comportamiento de Javascript, evaluando él mismo tu código y transformándolo antes de hacerlo. Puedes ver que en el ejemplo de PI que enlazas, el código de la demo está declarado como type=»text/sjs».

  • Otro modo de simular threads: (antigua, y solo funciona en navegadores guays) http://www.neilmix.com/2007/02/07/threading-in-javascript-17/ Es básicamente un comportamiento parecido a los threads en python (se van ejecutando instrucciones hasta que se para, entonces se continua en otro hilo)

  • Me hace mucha gracia que llamen «Multitarea» a lo que no es «Multitarea»

    Me parece que estás confundido con el tema de Apple y las definiciones , multitarea es la capacidad de realizar varias acciones a la vez, cosa que si se puede hacer perfectamente, esta puede ser implementada de diferentes formas , cooperativa ,por preferencias etc… por servicios compartidos

    la palabra multitarea no implica que tengan que estar todos los hilos corriendo y abiertos , simplemente implica que se pueden hacer más de una tarea a la vez cosa que es totalmente cierta.

    En el caso de apple es multitarea por preferencia y compartida , pero es multitarea pura y dura.

    http://en.wikipedia.org/wiki/Computer_multitasking

    Saludos felicidades por el blog

    • @Luisi: La base de la multitarea es que se ejecuten procesos simultáneamente, y según parece (en el artículo de Applesfera) la versión de Apple paraliza por completo el proceso que abandondamos para dedicar los recursos a la aplicación que abrimos.

      De esta forma, al volver a la aplicación congelada nos permite continuar por donde íbamos.

      Como dices es multitarea por preferencia y compartida, salvo que en lugar de que procesador decida donde dedicar más recursos, eres tu que decides que abres y que cierras… como tu mismo dices, pura y dura 😀

  • «La base de la multitarea es que se ejecuten procesos simultáneamente»

    Yo creo que eso se llama multiproceso.

    «Como dices es multitarea por preferencia y compartida, salvo que en lugar de que procesador decida donde dedicar más recursos, eres tu que decides que abres y que cierras… según que servicios»

    Pues ahí mismo lo estás diciendo. Un molinillo de cafe es un molinillo de cafe , sea a manivela o automático. ¿no? Véase que me estoy refiriendo a definiciones no a la calidad o no eso es aparte.

    Un saludo.

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.