Dependiendo del introducirde estructura de datos, MemoryStoreService impone límites en la memoria y el número de elementos en una estructura de datos.Todas las estructuras de datos también están limitadas por un límite global por partición.
Cada experiencia de Roblox tiene el Panel de observabilidad de la tienda de memoria, que incluye un conjunto de gráficos que puedes usar para monitorear el uso de la tienda de memoria.
Mapas y colas ordenados
Ambos, mapas ordenados y colas, tienen límites en el número máximo de artículos y en la memoria total máxima.Además, los elementos en una de estas estructuras de datos siempre residen en una sola partición.Cada solicitud a una de esas estructuras de datos es una solicitud a la misma partición.
Cuando un mapa o colas ordenados alcanza su límite de elementos o memoria, la mejor opción es eliminar elementos innecesarios manualmente o agregando una política de expiración para los elementos.Alternativamente, si solo el límite de memoria causa estrangulamiento, puedes intentar reducir el tamaño de tus elementos al eliminar información innecesaria de tus claves y valores.
Si necesita todos sus artículos o está experimentando un cuello de botella debido a la velocidad de solicitud, la única solución es la fragmentación.
Fragmentación
Fragmentación es el proceso de almacenar un conjunto de datos relacionados en múltiples estructuras de datos.En otras palabras, significa tomar una estructura de datos existente de alto rendimiento y reemplazarla con múltiples estructuras más pequeñas que, juntas, contienen el mismo conjunto de datos que el original.
El desafío clave para fragmentar es encontrar una manera de distribuir los datos en múltiples estructuras de datos de manera que mantenga la misma funcionalidad que el original.
Fragmentar un mapa ordenado
Para dividir un mapa ordenado, considere dividir sus datos en subsecciones alfabéticas con rangos de caracteres.Por ejemplo, suponga que solo tiene claves con la primera letra de A-Z y cree que cuatro mapas ordenados son suficientes para su caso de uso actual y su crecimiento futuro:
- El primer mapa puede cubrir A-G, el segundo H-N, el tercero O-T, y el cuarto U-Z.
- Para insertar o recuperar un objeto, utilice el mapa apropiado basado en el personaje inicial del objeto.
Fragmentar un mapa ordenado
-- Inicializar el servicio MemoryStore
local MemoryStoreService = game:GetService("MemoryStoreService")
-- Crea tus cubos de mapa ordenados
local sm_AtoG = MemoryStoreService:GetSortedMap("AtoG")
local sm_HtoM = MemoryStoreService:GetSortedMap("HtoM")
local sm_NtoT = MemoryStoreService:GetSortedMap("NtoT")
local sm_UtoZ = MemoryStoreService:GetSortedMap("UtoZ")
-- Función ayudante para recuperar el cubo correcto desde la clave del artículo
local function getSortedMapBucket(itemKey)
if (itemKey >= "a" and itemKey < "h") then
return sm_AtoG
elseif (itemKey < "n") then
return sm_HtoM
elseif (itemKey < "u") then
return sm_NtoT
else
return sm_UtoZ
end
end
-- Inicializar nombres de jugadores con valor predeterminado de 0
for _, player in game:GetService("Players"):GetPlayers() do
local bucket = getSortedMapBucket(player)
bucket:SetAsync(player, 0, 600)
end
-- Recuperar el valor de un jugador
local player = "myPlayer"
local bucket = getSortedMapBucket(player)
local playerScore = bucket:GetAsync(player)
print(playerScore)
Fragmentar una cola
Dividir una cola es más complicado que dividir un mapa ordenado.Aunque quieras distribuir la capacidad de solicitudes a través de múltiples colas, las adiciones, lecturas y eliminaciones solo ocurren siempre en la parte delantera o trasera de la cola.
Una solución es usar una cola rotatoria, lo que significa crear múltiples colas y rotar entre ellas cuando agregues o leas un objeto:
Crea varias colas y agrégalas a un matriz/lista.
Crea dos puntos locales. Uno representa la cola de la que quieres leer y eliminar artículos. El otro representa la cola a la que quieres agregar artículos:
- Para operaciones de lectura, calcula el número de elementos que necesitas de cada cola, así como dónde mover el puntero de lectura.
- Para eliminar operaciones, pase los ID de la lectura a cada cola.
- Para agregar operaciones, agregue a la cola en el punto de agregación y aumente el puntero.
Fragmentar una cola
-- Inicializar el servicio MemoryStore
local MemoryStoreService = game:GetService("MemoryStoreService")
-- Crea tus colas
local q1 = MemoryStoreService:GetQueue("q1")
local q2 = MemoryStoreService:GetQueue("q2")
local q3 = MemoryStoreService:GetQueue("q3")
local q4 = MemoryStoreService:GetQueue("q4")
-- Poner las colas en un array
local queueArr = { q1, q2, q3, q4 }
-- Crear dos punteros que representen los índices de la lectura y la adición de colas
local readIndex = 1
local addIndex = 1
-- Crea una función local que actualice los índices apropiadamente
local function rotateIndex(index, n)
return (index + n - 1) % 4 + 1
end
-- Crea una función local que lee n artículos de la cola
local function readFromQueue(count, allOrNothing, waitTimeout)
local endIndex = count % 4
local countPerQueue = count // 4
local items = {}
local ids = {}
-- bucle a través de cada cola
for i = 1, 4, 1 do
-- determinar si esta cola leerá un artículo objeto
local diff = i - readIndex
if diff < 0 then
diff += 4
end
local queue = queueArr[i]
-- leer artículos de cada cola
-- +1 artículos si coinciden con los criterios de lectura adicionales
if diff < endIndex then
items[i], ids[i] = queue:ReadAsync(countPerQueue + 1, allOrNothing,waitTimeout)
else
items[i], ids[i] = queue:ReadAsync(countPerQueue, allOrNothing,waitTimeout)
end
end
readIndex = rotateIndex(readIndex, count)
return items, ids
end
-- Crea una función local que elimina n artículos de la cola
local function removeFromQueue(ids)
for i = 1, 4, 1 do
local queue = queueArr[readIndex]
queue:RemoveAsync(ids[i])
end
end
-- Crea una función local que agrega un artículo a la cola
local function addToQueue(itemKey, expiration, priority)
local queue = queueArr[readIndex]
queue:AddAsync(itemKey, expiration, priority)
addIndex = rotateIndex(addIndex, 1)
end
-- ¡Escribe algo de código!
for _, player in game:GetService("Players"):GetPlayers() do
addToQueue(player, 600, 0)
end
local players, ids = readFromQueue(20, true, -1)
removeFromQueue(ids)
Mapas de hash
Los mapas de hash no tienen límites de memoria o de cantidad de artículos individuales y se fragmentan automáticamente, pero aún puedes encontrar ralentizaciones si los usas mal.
Por ejemplo, considere una experiencia con un mapa de hash de datos de juego, almacenada como el valor de una sola clave llamada metadata .Si este metadato contiene un objeto anidado con información como el ID del lugar, el número de jugadores y más, cada vez que se necesita el metadato, no tienes más remedio que llamar GetAsync("metadata") y recuperar todo el objeto.En este caso, todas las solicitudes van a una sola clave y, por lo tanto, a una sola partición.
En lugar de almacenar todos los metadatos como un objeto único y anidado, el enfoque mejor es almacenar cada campo como su propia clave para que la tabla de hash pueda aprovechar la fragmentación automática.Si necesita separación entre el metadato y el resto del mapa de hash, agregue un prefijo de nombre (por ejemplometadata_user_count en lugar de solo user_count).