Большой изменяемый байтовый массив в Erlang - PullRequest
9 голосов
/ 16 августа 2011

Поскольку я пишу простое серверное приложение для Minecraft в Эрланге, меня сейчас волнует вопрос о том, как эффективно хранить и изменять данные чанка. Для тех, кто не знает о внутренностях Minecraft: мне нужно хранить много двоичных файлов (100-1000) размером до 32 КБ в памяти. До этого момента встроенных двоичных файлов Эрланга достаточно. Но сервер должен читать и изменять некоторые байты (по их идентификатору) в этих двоичных файлах довольно часто, и я не хочу копировать их все время.
Приятно иметь возможность импортировать и экспортировать из / в стандартные двоичные файлы Erlang.

Есть ли расширение или база данных Erlang или что-то еще, что я мог бы использовать для этого?

Ответы [ 3 ]

9 голосов
/ 16 августа 2011

Поскольку двоичные файлы доступны только для чтения, я могу подумать о следующих подходах (при условии, что вы ожидаете высокую скорость изменений):

  1. Используйте древовидную структуру с относительно небольшими неизменяемыми двоичными файлами в листьях.В этом случае, когда вы изменяете свои данные, вам нужно всего лишь заново создать небольшой двоичный лист + все узлы вплоть до корня.Предполагая, что изменения "локальны" для некоторой позиции, я думаю, вы можете начать с octo-tree.
  2. Использовать "большие" двоичные файлы + список изменений (это может быть простой список функций).Когда вам нужно изменить мир, просто добавьте новую функцию в список.Когда кто-то запрашивает состояние мира, возьмите базовый двоичный файл и примените все изменения из списка.Время от времени "сдавляйте" все изменения и готовьте новое двоичное состояние базового состояния.Это может быть объединено с предыдущим подходом (дерево с парами двоичных файлов / изменения в листах).
  3. Перемещение управления изменяемым миром во внешний код.Вы можете использовать NIFs или Порты .Я думаю, это был бы самый быстрый способ.Кроме того, я думаю, что это было бы относительно легко осуществить.Первая версия API может быть такой простой, как world:new(X, Y, Z) -> ref(); world:get(Ref, X, Y, Z); world:set(Ref, X, Y, Z, Value);
3 голосов
/ 16 августа 2011

Мое предложение состоит в том, чтобы использовать структуру "веревки". По сути, это древовидная структура, обычно это сплайс или пальчиковое дерево, в котором вы можете изменять только части дерева. Правильное выполнение этого позволяет вам получить лучшее из обоих миров: неизменность и быстрые обновления.

Я не знаю о реализации веревки, но это то, что вы хотите сделать.

Альтернативой является использование ets в качестве изменяемого массива. Это довольно быстро для такого рода вещей.

Третий вариант - использовать пространственную древовидную структуру для представления вашего мира. Octrees или BSP-подобная структура - это то, за что я бы слепо ухватился.

0 голосов
/ 16 августа 2011

1000 32kb бинарных файлов не имеет большого значения. вы говорите изменить несколько байтов? может быть, было бы лучше, если бы вы просто сделали запись различных частей, которые может содержать двоичный файл, или которые часто модифицируются, чтобы вы могли изменять части двоичного файла без копирования других. С ets вам не нужно беспокоиться о куче бинарных копий, ожидающих получения. Он все еще делает копию, и он все еще gc'ed, но не так, как процесс. Вы также можете использовать функцию fullsweep_after для более частой очистки процесса.

...