2011-09-20 23 views
16

Estoy trabajando en un juego de HTML 5, ya está en línea, pero actualmente es pequeño y todo está bien.Descarga de recursos en HTML con JavaScript

La cosa es, a medida que crece, va a cargar muchas, muchas imágenes, música, efectos de sonido y más. Después de 15 minutos de juego, al menos 100 recursos diferentes ya se pudieron haber cargado. Como es una aplicación HTML5, nunca refresca la página durante el juego, por lo que se acumulan en segundo plano.

Me he dado cuenta de que cada recurso que cargué, al menos en WebKit, usando Web Inspector, permanece allí una vez que elimino el <img>, <link> en el CSS y demás. Supongo que todavía está en la memoria, simplemente no se usa, ¿verdad?

Esto acabaría consumiendo mucha RAM eventualmente, y conduciría a una degradación en el rendimiento especialmente en los móviles iOS y Android (que ya noté ligeramente en la versión actual), cuyos recursos son más limitados que las computadoras de escritorio.

Mi pregunta es: ¿Es posible descargar por completo un recurso, liberando espacio en la memoria RAM, a través de JavaScript? Sin tener que actualizar toda la página para "limpiarla".

Peor escenario: ¿Usaría marcos ayuda, al eliminar un marco, para liberar esos marcos de recursos ?.

¡Gracias!

+3

Una cosa que podría intentar hacer es establecer el manejador de recursos correspondiente en 'null'.Mientras el recurso ya no esté referenciado desde ningún lugar, la memoria que usa debe ser recolectada por el motor de JavaScript –

+0

. ¡Voy a probar eso! ¡Gracias! ¿Te importa compartir conmigo un enlace con ejemplos sobre cómo acceder a los recursos que el navegador ha cargado? Me está costando encontrar eso en Google =/ – ArtPulse

+0

En Firefox y Chrome, el recolector de basura parece ejecutarse cuando se cambia a otra pestaña. No estoy seguro de lo útil que esto es para ti, pero si el usuario no juega continuamente, deberías estar bien confiando en el recolector de basura. – pimvdb

Respuesta

3

Su descripción implica que ha eliminado por completo todas las referencias a los recursos. El comportamiento que está viendo, entonces, es simplemente el recolector de basura que no se ha invocado para limpiar el espacio, que es común en las implementaciones de javascript hasta que sea "necesario". Establecer en null o llamando al delete generalmente no lo hará mejor.

Como un caso común, normalmente puede llamar al CollectGarbage() durante cargas/descargas de escenas para forzar el proceso de recopilación. Esta suele ser la mejor solución cuando los datos se cargarán para "etapas" del juego, ya que es un tiempo que no es crítico en el tiempo. Por lo general, no deseas que el coleccionista invoque durante el juego a menos que no sea un juego en tiempo real.

Los marcos suelen ser una solución difícil si desea mantener ciertos recursos para controles de juego comunes. Debe considerar si está actualizando recursos completos o solo ciertos recursos.

+0

¡Sí! Es por eso que quería evitar el uso de marcos. No quiero duplicados de mis recursos, tiene que ser optimizado. - Entonces, ¿estás diciendo que al invocar ese método, JS borrará de mi memoria todo lo que no estoy usando en ese momento exacto? (como las imágenes que están cargadas, pero que no están insertadas en el HTML en ninguna parte?) – ArtPulse

+0

@ArtPulse: se supone que obliga a su funcionamiento, aunque he visto algunas implementaciones más antiguas interpretarlo como una pista. Entonces, todos los objetos sin referencia se eliminarán. Por lo general, es mejor comenzar simplemente agregando recursos y verificar que la operación de fondo de GC es insuficiente antes de considerar su uso, pero los desarrolladores de juegos lo han usado con más frecuencia porque conocen lugares donde puede recolectarse un GC sin interferir con el juego. – ex0du5

+0

¡Muy bien! Pero, ¿elimina solo las variables JS no utilizadas? ¿Qué sucede si una imagen que se descargó mediante una etiqueta en el HTML ya no está siendo utilizada por ninguna etiqueta y, por lo tanto, no está en uso? ¿GC eliminará ese recurso? – ArtPulse

1

Dijiste peor escenario: ayudaría utilizando marcos, mediante la supresión de un marco, para liberar recursos de esos marcos

Es bueno utilizar marco. Sí, puede liberar recursos eliminando los marcos.

+0

¿Funciona? Bueno, al menos eso es a prueba de fallas. Podría cargar una Batalla completa en un marco, por ejemplo, y una vez hecho, matarlo. Trataré de ver cómo responde. – ArtPulse

+0

Disuadiría el uso de marcos. De hecho, soltaron la etiqueta '' en HTML5 http://www.w3.org/TR/html5-diff/ – Alex

+0

No me gustan los marcos. Es por eso que no quiero usarlos xD – ArtPulse

3

Todo lo que puede hacer es confiar en el mecanismo de recolección de basura integrado de JavaScript.

Esto entra en juego siempre que no haya ninguna referencia a su imagen.

Así que suponiendo que tiene un indicador de referencia para cada imagen, si se utiliza:

img.destroy() 

o

img.parentNode.removeChild(img) 

Merece la pena echar un vistazo a: http://www.ibm.com/developerworks/web/library/wa-memleak/

también: Need help using this function to destroy an item on canvas using javascript

EDITAR

Aquí hay un código que le permite cargar una imagen en una var.

<script language = "JavaScript"> 


var heavyImage = new Image(); 
heavyImage.src = "heavyimagefile.jpg"; 

...... 

heavyImage = null; // removes reference and frees up memory 

</script> 

Esto es mejor que el uso de jQuery .load() becuase que le da más control sobre referencias de imagen, y se elimina de la memoria si la referencia se ha ido (null)

Tomado de: http://www.techrepublic.com/article/preloading-and-the-javascript-image-object/5214317

Espero que ayude!

+0

Cada parte se carga a través de jQuery.load(), que inserta etiquetas HTML con , entre otras cosas. Así es como funciona todo, en realidad. Al eliminarlos, aún son visibles en Web Inspector. ¿Quiere decir que debería cargar todas las imágenes de JavaScript para poder "descargarlas" de JavaScript también? – ArtPulse

+0

Eso suena genial. Sin embargo, implementar todo en el juego a través de este medio tomaría más tiempo y cambiaría mucho de lo que ya se había hecho. Pero lo tendrá en cuenta como una posibilidad, gracias =) – ArtPulse

+0

No olvide que puede usar un 'Array()' para contener varias imágenes (si eso ayuda) – Alex

0

Muy bien, así que hice mis pruebas cargando 3 HTML diferentes en una etiqueta de artículo <>. Cada HTML tenía muchas, enormes imágenes. Unas 15 imágenes enormes por "página".

Así que utilicé la función jQuery.load() para insertar cada una en la etiqueta. También tenía un código HTML adicional que solo tenía un < h1>, para ver qué sucedía cuando una página sin imágenes reemplazaba a la página anterior.

Bueno, resulta que la memoria RAM va más grande cuando comienzas a desplazarte, y dispara cuando pasas por una imagen particularmente grande (grande en dimensiones y tamaño, no solo en tamaño). Pero una vez que lo dejas atrás y las imágenes más claras llegan a la pantalla, el consumo de RAM realmente baja. Y cada vez que reemplazaba usando JS el contenido de la página, el consumo de RAM disminuía mucho cuando ocupaba demasiado. La memoria virtual se mantuvo siempre alta y raramente descendió.

Supongo que el navegador es bastante inteligente sobre el manejo de recursos. No parece descargarlos si lo dejas ahí por un largo tiempo, pero tan pronto como empiezas a cargar otras páginas o al desplazamiento, comienza a cargar/liberar.

supongo que no tengo nada de qué preocuparse después de todo ...

Gracias a todos! =)

3

Hay 2 formas mejores para cargar las imágenes, además de un <img> etiqueta normal, lo que Google brillantemente discute aquí:

http://www.youtube.com/watch?v=7pCh62wr6m0&list=UU_x5XG1OV2P6uZZ5FSM9Ttw&index=74

  1. Cargando las imágenes a través de una HTML5 <canvas> que se forma en forma Más rápido. Realmente vería ese video e implementaría estos métodos para obtener más velocidad. Me imagino que la recolección de basura con lienzo funcionaría mejor porque se está separando del DOM.

  2. Urls de datos incrustados, donde el atributo src de una etiqueta de imagen son los datos binarios reales de la imagen (sí, es una cadena gigante). Comienza así: src="data:image/jpeg;base64,/9j/MASSIVE-STRING ... " Después de usar esto, por supuesto querrá usar un método para eliminar este nodo como se discutió en las otras respuestas. (No sé cómo generar esta cadena de base64, pruebe Google o el video)

+1

¡Suena bien! Definitivamente lo tendré en cuenta. Gracias Devin! – ArtPulse

+0

eh todos debemos ofrecer nuestro tiempo de voluntariado a otros en StackOverflow –