2011-08-23 14 views
5

Estoy haciendo un juego con Scala.Hacer mi List.filter más rápido en Scala?

Mi juego tiene varias piscinas para mantener a los enemigos. Son listas inmutables porque se inicializaron a un tamaño que debería ser suficiente (porque la creación de nuevas instancias enemigas durante el juego es muy costosa).

Mi juego sabe si un enemigo está vivo preguntando enemy.isVisible. Así que mi CollisionHandler funciona como:

  1. Combinar todos los enemigos en vivo a una lista
  2. Consigue munición real
  3. partición del espacio estos y hacer la detección de colisión para las balas y enemigos en la misma partición del espacio

Lo que me sorprendió fue que según el perfilador, el paso 1 lleva la mayor parte del tiempo. Y lo que paso hace es básicamente dicen:

def allActiveEnemies = List(enemyType1.getAllActive, enemyType2.getAllActive, ...).flatten 

la flatten allí no parece caro, pero en vez de eso es recibir llamadas getAllActive. Se llevan a cabo en mi rasgo agrupado así:

trait Pooled[T <: Entity] { 
    var pool = List[T]() 
    val INITIAL_POOL_SIZE:Int 

    def initPool() { 
     for(i<-1 to INITIAL_POOL_SIZE) 
     { 
      addToPool(disable(createNew)) 
     } 
    } 

    def getAllActive:List[T] = pool.filter(e => e.isVisible) 
} 

(que omite la mayor parte del rasgo porque yo no creo que es relevante aquí.)

pool.filter es lo que quema como el 45% de la tiempo total pasado en CollisionHandler, lo que parece realmente extraño.

¿Alguna sugerencia para hacer las cosas más rápido aquí?

¿Quizás usando ArrayLists en lugar de List? ¿Tal vez usando algunas colecciones de clasificación y mutables? ¿O simplemente estoy haciendo algo terriblemente malo?

Gracias!

+0

es 'e.isVisible' un acceso de campo o un cálculo? – huynhjl

+0

isVisible es un getter para un campo (ya que estoy usando un motor de juego basado en Java como base de mi juego). – vertti

+0

Probablemente debería agregar que estoy usando Scala 2.8.1 y el juego se ejecuta en Android 2.x – vertti

Respuesta

4

¿Cuán grandes son estas piscinas? Usted sabe que cada vez que hace una lista, debe crear un nuevo objeto para contener cada entrada. Puede reducir un poco esto usando una vista en el filtro (es decir, pool.view.filter(e => e.isVisible); luego, devuelva Seq[T]). En general, creo que su estrategia debe ser no hacer un trabajo de filtrado adicional cada vez. Haz un seguimiento de tus enemigos activos en un Set o algo así; luego los tienes cuando los necesitas.

+0

Las piscinas tienen actualmente alrededor de 40 y hay como 5 de ellas. Pero ambos números crecerán a medida que avancemos en nuestro juego, por lo que supongo que el tamaño de la agrupación será de alrededor de 100 y de 10 a 15 grupos. – vertti

+0

@vertti - Eso no debería tomar ningún tiempo notable en absoluto, quizás un milisegundo o dos en el peor de los casos. –

+0

Perfil de Android dice alrededor de 27 mseg para CollisionHandler, la mitad de eso para los filtros getActive. :(Eso ya es suficiente para afectar las tasas de fotogramas considerablemente. – vertti

Cuestiones relacionadas