2011-08-15 16 views
9

Como estoy escribiendo una sencilla aplicación de servidor de Minecraft en Erlang, ahora me preocupa la cuestión de cómo almacenar y modificar datos de fragmentos de manera eficiente. Para aquellos que no saben acerca de las partes internas 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.Gran matriz de bytes mutable en Erlang

¿Hay alguna extensión o base de datos Erlang o lo que sea que pueda usar para esto?

+0

Al final, el problema se resolvió usando binarios de 4kB de tamaño cada uno y edificándolos para cada cambio de bloque. Si bien esta no es la última palabra en términos de eficiencia de actualización, pero ahorra memoria. En caso de que quiera echar un vistazo, el código está disponible en [Github] (https://github.com/clonejo/mc-erl). – clonejo

Respuesta

9

Dado que son de sólo lectura binarios, puedo pensar en los siguientes enfoques (suponiendo que espera un alto índice de cambios):

  1. Uso estructura de árbol con relativamente pequeños binarios inmutables 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.
  2. Utilice "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).
  3. Mueva la administración mundial mutable al código externo. Puede usar NIFs o Ports. 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);
+0

¡Gracias por tu gran respuesta! Supongo que usaré la segunda forma, ya que los cambios no son tan frecuentes (no más de 5 bytes por segundo y jugador). – clonejo

0

1000 binarios de 32kb no es 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. Todavía hace una copia y sigue siendo 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.

3

Mi sugerencia es utilizar 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 desea hacer.

Una alternativa es usar ets como una matriz mutable. Es bastante rápido para ese tipo de cosas.

La tercera opción es utilizar una estructura de árbol espacial para representar su mundo. Los octrees o una estructura tipo BSP es algo que agarraría, ciegamente.

Cuestiones relacionadas