arrays - Gran matriz de bytes mutables en Erlang
memory minecraft (3)
Mientras escribo una sencilla aplicación de servidor de Minecraft en Erlang, ahora me preocupa la cuestión de cómo almacenar y modificar de manera eficiente los datos de fragmentos. Para aquellos que no saben sobre el funcionamiento interno de Minecraft: Necesito almacenar una gran cantidad de binarios (100-1000) de hasta 32kB de tamaño en la memoria. Hasta este punto, los binarios integrados de Erlang son suficientes. Pero el servidor tiene que leer y cambiar algunos bytes (por su id) en estos binarios con bastante frecuencia y no quiero copiarlos todo el tiempo.
Una característica agradable de tener sería importar y exportar desde / a los binarios estándar de Erlang.
¿Hay alguna extensión o base de datos Erlang o lo que sea que pueda usar para esto?
1000 binarios de 32kb no son un gran problema. dices cambiar algunos bytes? tal vez sería mejor si acaba de hacer un registro de las diferentes partes que el binario puede contener o que a menudo se modifican, de esa manera puede modificar partes del binario sin copiar otras. Con ets no tienes que preocuparte por un montón de copias binarias que esperan ser copiadas. Aún hace una copia y todavía está en gc pero no de la misma manera que un proceso. También puede usar el comando fullsweep_after para optar por realizar una limpieza de proceso más a menudo.
Como los archivos binarios son de solo lectura, puedo pensar en los siguientes enfoques (suponiendo que espere una alta tasa de cambios):
- Use una estructura similar a un árbol con binarios inmutables relativamente pequeños en las hojas. En ese caso, cuando modifique sus datos, solo necesita volver a crear pequeños binarios + todos los nodos hasta la raíz. Suponiendo que los cambios sean "locales" en alguna posición, creo que puedes comenzar con octoboar.
- Use "grandes" binarios + lista de cambios (que podría ser una simple lista de funciones). Cuando necesite modificar el mundo, simplemente agregue una nueva función a la lista. Cuando alguien pregunta por el estado mundial, tome el binario base y aplique todos los cambios de la lista. De vez en cuando "aplastar" todos los cambios y preparar un nuevo binario de estado de línea base. Esto podría combinarse con el enfoque anterior (árbol con pares de cambios binarios / en las hojas).
- Mueva la administración mundial mutable al código externo. Puede usar NIFs o Puertos . Creo que esa sería la forma más rápida. Además, creo que sería relativamente fácil implementarlo. La primera versión de API podría ser tan simple como
world:new(X, Y, Z) -> ref(); world:get(Ref, X, Y, Z); world:set(Ref, X, Y, Z, Value);
world:new(X, Y, Z) -> ref(); world:get(Ref, X, Y, Z); world:set(Ref, X, Y, Z, Value);
Mi sugerencia es usar una estructura de "cuerda". Básicamente es una estructura parecida a un árbol, por lo general un árbol en forma de dedo o en forma de dedo en el que solo permite cambiar partes del árbol. Hacer esto de la manera correcta te permite tener lo mejor de ambos mundos: inmutabilidad junto con actualizaciones rápidas.
No sé de una implementación de cuerda, pero esto es lo que quieres hacer.
Una alternativa es usar ets como una matriz mutable. Es bastante rápido para ese tipo de cosas.
La tercera opción es usar una estructura de árbol espacial para representar tu mundo. Los octrees o una estructura tipo BSP es algo que agarraría, ciegamente.