Mover instancias de Set a otro en Scala
En un juego necesito mantener las pestañas de cuál de mis sprites agrupados están en uso. Cuando "activo" múltiples sprites a la vez quiero transferirlos de mi passivePool
a activePool
ambos de los cuales son inmutables HashSets (ok, voy a estar creando nuevos conjuntos cada vez para ser exactos). Así que mi idea básica es a lo largo de las líneas de:
activePool ++= passivePool.take(5) passivePool = passivePool.drop(5)
pero la lectura de la documentación scala supongo que los 5 que tomo podría ser diferente que el 5 que luego caer. Que definitivamente no es lo que quiero. También podría decir algo como:
- Android Views: ¿puede comprobar la visibilidad antes de configurar la visibilidad y mejorar el rendimiento?
- Acceso al campo local vs campo de objeto. ¿Está mal el documento?
- Está llamando libgdx SpriteBatch método de inicio y fin varias veces caro?
- Descifrado AES en Android demasiado lento para ser utilizable. ¿NDK será más rápido? ¿Otras ideas?
- Cómo mejorar el rendimiento de JS menú arrastrar en WebView en Android
val moved = passivePool.take(5) activePool ++= moved passivePool --= moved
pero como esto es algo que tengo que hacer casi todos los fotogramas en tiempo real en un dispositivo limitado (teléfono Android) Supongo que esto sería mucho más lento, ya que tendré que buscar uno por uno cada uno de los sprites moved
de la passivePool
.
¿Alguna solución inteligente? ¿O me falta algo básico? Recuerde que la eficiencia es una preocupación principal aquí. Y no puedo usar listas en lugar de conjuntos porque también necesito la eliminación de acceso aleatorio de sprites de activePools cuando los sprites se destruyen en el juego.
- Android: utiliza UUID como clave principal en SQLite
- Android: WebView mejora la velocidad de carga de los archivos html locales
- Cómo reducir el tamaño de WebView dinámicamente de acuerdo a su contenido?
- Impacto de 'instanceof' en el código Java de Android
- Cuál es la ventaja de usar el espacio sobre la vista
- Hex to String en Java El rendimiento es demasiado lento
- Vista de lista optimizada con 1k lista de objetos
- Android TextureView / Dibujo / Rendimiento de la pintura
No hay nada como benchmarking para obtener respuestas a estas preguntas. Vamos a tomar 100 juegos de tamaño 1000 y dejarlos caer 5 a la vez hasta que estén vacíos, y ver cuánto tiempo toma.
passivePool.take(5); passivePool.drop(5) // 2.5 s passivePool.splitAt(5) // 2.4 s val a = passivePool.take(5); passivePool --= a // 0.042 s repeat(5){ val a = passivePool.head; passivePool -= a } // 0.020 s
¿Qué está pasando?
La razón por la que las cosas funcionan de esta manera es que inmutable.HashSet se construye como un hash trie con optimizado (efectivamente O(1)
) agregar y quitar operaciones, pero muchos de los otros métodos no se vuelven a implementar; en su lugar, se heredan de colecciones que no admiten add / remove y por lo tanto no puede obtener los métodos eficientes de forma gratuita. Por lo tanto, en su mayoría reconstruir todo el conjunto hash desde cero. A menos que su conjunto hash tiene sólo un puñado de elementos en él, esto es mala idea. (En contraste con la desaceleración 50-100x con conjuntos de tamaño 1000, un conjunto de tamaño 100 tiene "sólo" una desaceleración 6-10x ….)
Por lo tanto, la línea de fondo: hasta que la biblioteca se ha mejorado, hacerlo de manera "ineficiente". Serás mucho más rápido.
Creo que puede haber un cierto kilometraje en el uso de splitAt
aquí, que le devolverá tanto los cinco sprites para moverse y la piscina recortada en una única invocación de método:
val (moved, newPassivePool) = passivePool.splitAt(5) activePool ++= moved passivePool = newPassivePool
Puntos de bonificación si puede asignar directamente de nuevo a passivePool
en la primera línea, aunque no creo que sea posible en un breve ejemplo en el que está definiendo la nueva variable moved
también.