2011-02-15 6 views
14

Lo he escuchado y lo he experimentado yo mismo: el recolector de basura de Lua puede causar caídas graves de FPS en los juegos a medida que crece la parte de sus guiones.¿Por qué Lua usa un recolector de basura en lugar de contar la referencia?

Esto es lo que descubrí relacionado con el recolector de basura, donde, por ejemplo, todos los objetos userdata Vector() creados se encuentran temporalmente hasta que se recoge la basura.

Sé que Python utiliza el recuento de referencias, y es por eso que no necesita grandes pasos para comer como Luas GC.

  • ¿Por qué Lua no utiliza el recuento de referencias para deshacerse de la basura?
+0

No hay problemas con FPS en Lua 5.1 siempre y cuando configure correctamente el recolector de basura incremental. –

+0

De hecho, el problema real es la velocidad de fotogramas inestable causada por la operación diferida/ráfaga, no la caída del fotograma. El GC completo per-tick o el GC incremental/concurrente pueden disminuir mucho este tipo de operaciones, pero no completamente. La operación de ráfaga puede ser causada si la memoria no es suficiente para mantener las guardas arriba. (o crash :) – Eonil

Respuesta

15

Porque los recolectores de basura de conteo de referencia pueden filtrar fácilmente objetos.

Ejemplo trivial: una lista doblemente vinculada. Cada nodo tiene un puntero al siguiente nodo, y el siguiente lo señala. Si solo quita la referencia de la lista y espera que se recopile, acaba de filtrar toda la lista - ninguno de los nodos tiene un recuento de referencia de cero, y por lo tanto, todos se mantendrán vivos. Con un recolector de basura de conteo de referencia, cada vez que tenga un objeto cíclico, básicamente debe considerarlo como un objeto no administrado y deshacerse de él de manera explícita cuando termine.

Tenga en cuenta que Python utiliza un recolector de basura adecuado además del recuento de referencias.

5

Recuento de referencia solo no es suficiente para que un recolector de basura funcione correctamente porque no detecta ciclos. Incluso Python no utiliza el recuento de referencias solo.

Imagine que los objetos A y B tienen una referencia el uno al otro. Incluso una vez que el programador ya no tenga una referencia a ninguno de los objetos, el recuento de referencias seguirá indicando que los objetos A y B tienen referencias que los señalan.

Existen muchos esquemas diferentes de recolección de basura y algunos funcionarán mejor en algunas circunstancias y algunos funcionarán mejor en otras circunstancias. Depende de los diseñadores del idioma el intentar elegir un recolector de basura que creen que funcionará mejor para su idioma.

3

En general, el recuento de referencias no es un sustituto exacto de la recolección de basura debido al potencial de las referencias circulares. Es posible que desee leer this page sobre por qué es preferible la recolección de basura para el recuento de referencias.

+0

Creo que realmente lo enganché cuando traté de equilibrar la guerra santa entre GC y RC. GC _es_ la mejor forma de administrar la RAM. Sin embargo, aún se necesita RC para administrar otros recursos (mutexes, archivos, bases de datos, conectores, etc.) –

+0

@deft_code: Estoy totalmente de acuerdo. Simplemente no me gusta el hecho de que la palabra clave 'delete' esté en desuso, aunque ... :( – Mehrdad

10

Mientras que otros han explicado por qué necesita un recolector de basura, tenga en cuenta que puede configurar los ciclos de recolección de basura en Lua para que sean más pequeños, menos frecuentes o bajo demanda. Si tienes mucha memoria asignada y estás ocupado dibujando marcos, entonces haz que los umbrales sean muy grandes para evitar un ciclo de recolección hasta que haya un descanso en el juego.

Lua 5.1 Manual on garbage collection

+0

¿Crees que puedes [ayuda aquí] (http://stackoverflow.com/questions/41080633/why-is -llg-defaultmeta-value-gc-always-null)? – displayname

6

¿Qué versión de Lua está siendo utilizado en los juegos que están basando esta afirmación en? Cuando World of Warcraft cambió de Lua 5.0 a 5.1, todos los problemas de rendimiento causados ​​por la recolección de basura se redujeron severamente.

Con la recolección de basura de Lua 5.0, la cantidad de tiempo dedicado a recolectar basura (y bloquear todo lo demás al mismo tiempo) era proporcional a la cantidad de memoria actualmente en uso, lo que provoca un gran esfuerzo para minimizar la uso de memoria de los complementos WoW.

Con la recolección de elementos no utilizados de Lua 5.1, el recolector ha cambiado a ser incremental para que no bloquee el juego mientras se recoge la basura como lo hacía anteriormente. Ahora la recolección de basura tiene un impacto mínimo en el rendimiento en comparación con el problema más grande de código horriblemente ineficiente en la mayoría de los complementos creados por el usuario.

2

Eche un vistazo a algunas de las fuentes de CPython. Una buena parte del código C es Py_DECREF y Py_INCREF. Ese libro desagradable, tedioso y propenso a errores simplemente se va en Lua.

Si es necesario, no hay nada que le impida escribir los módulos Lua en C que gestionan las asignaciones pesadas y privadas de forma manual.

1

Es una compensación. La gente ha explicado algunas razones por las que algunos lenguajes (esto realmente no tiene nada que ver con Lua) usan coleccionistas, pero no han tocado los inconvenientes.

Algunos lenguajes, especialmente ObjC, usan recuento de referencias exclusivamente. La gran ventaja de esto es que la desasignación es determinista: tan pronto como suelta la última referencia, se garantiza que el objeto se liberará inmediatamente. Esto es crítico cuando tienes restricciones de memoria. Con el asignador de Lua, si las restricciones de memoria requieren desasignación predecible, debe agregar métodos para forzar la liberación inmediata del almacenamiento subyacente, lo que frustra el punto de tener la recolección de basura.

"WuHoUnited" es incorrecto al decir que no se puede hacer esto, funciona muy bien con ObjC en iOS y con shared_ptr en C++. Solo tienes que entender el entorno en el que te encuentras para evitar ciclos o romperlos cuando sea necesario.

+0

Una de las maneras en que puede evitar o interrumpir ciclos es mediante el uso de punteros débiles. Una lista doblemente enlazada que usa punteros inteligentes probablemente debería estar usando un puntero débil para uno de los dos, por ejemplo, prev es débil y el siguiente es compartido. Desafortunadamente, no existe una referencia débil en Lua. –

Cuestiones relacionadas