Cacharreando Jobs


Este asunto de los Jobs requería un poco de estudio, así que acudí a San Google para orientarme al respecto y me bajé un tutorial de Youtube. Resulta que estaba dando palos de ciego, como suele suceder cuando uno se mete en cosas sin estudiar de antemano todos los elementos implicados.
Comienzo con respuesta a mi duda: los Jobs no son hilos. En realidad, son operaciones (o kernels) que se ejecutan en hilos de trabajo. Aparentemente, no son una solución mágica para todo, su verdadero valor se revela cuando necesitas descargar operaciones pesadas del hilo principal, para que éste haga otras cosas. Es recomendable realizar pruebas de rendimiento para ver si en verdad, convertir algo en Job es más rentable que hacerlo en tu Update(), a la manera tradicional.
Existen un montón de tipos diferentes de Jobs. Para mí ahora solo son importantes dos: el normal y el paralelo (IJob/IJobParallelFor). El primero ejecuta una operación, el segundo, trabaja sobre un arreglo, ejecutando una operación en paralelo sobre cada elemento del mismo. O sea, podemos crear un IJobParallelFor que tome un arreglo de conexiones de clientes y envíe o lea datos de cada una de ellas, en paralelo, o hasta donde los permitan los  worker threads de Unity, que supongo dependan de los núcleos disponibles en el CPU.
De los componentes del famoso Data Oriented Technology Stack, quizás los Jobs sean los más fáciles de comprender, aunque no carecen de detalles conflictivos. Estamos hablando de código que se ejecuta concurrentemente, con posibilidades de causar todo tipo de desastres si escribimos en un mismo lugar desde dos operaciones diferentes. Hay margen de sobra para meter la pata, causar race conditions y jodernos la vida con facilidad. Veamos un ejemplo, a modo de mini tutorial:

struct Prueba: IJob
{
  public int ttt;
 
  public void Execute()
  {
     /*  Hacer algo muy complicado con ttt */
  }
}

public class LoQueSea: MonoBehaviour
{
  private JobHandle handle;

  void Update()
  {
    int t;
    var job = new Prueba() {
      ttt = t
    }
    //programar su ejecucion
    handle= job.Schedule(handle);
    /* Hacer otras cosas */
    /* Importante!! Aqui no podemos modificar las variables que el job esta usando */
    handle.Complete(); //completamos el Job
   
  }
}

Sin embargo, si creen que usar Jobs aumenta el rendimiento, esperen a combinarlos con el Burst Compiler. El resultado me hubiera hecho caerme de culo de no haber estado sentado. Basta con agregar el atributo [BurstCompile]:

[BurstCompile]
struct Prueba: IJob


Como ven, nada que un programador no pueda entender con un tutorial básico y una hora de estudio. Usarlo adecuadamente ya es otra cosa.
Para concluir, les recuerdo que pueden comprar la novela en Amazon.  Arriba, que no he logrado una venta este mes y así no podré comprarme el yate.

Comentarios