Here you go
--[[
ManualMemoryManagement
Made by Alexandru2201913
This module brings Manual Memory Management to Luau in Roblox.
The main reason to use this module is to skip the GC (garbage collector),
effectively improving performance in all scripts.
The default size for allocation in memory is exactly 1GB. You can change
it to whatever size you want, with the condition of staying under 1GB.
If used by a LocalScript, this memory is allocated to the client's RAM.
Use responsibly, as you can cause memory leaks on the client's machine,
which will trigger OOM, which may result in a BSOD and possible data
loss.
This script can be used much more effectively by adding the '--!native'
flag to your scripts. They will be compiled AOT, and memory operations
are much faster done by a compiled environment than an interpreted one.
]]
--!native
-- Master Instances
local ManualMemoryManagement = {} -- Module that will store all of our functions.
local buffer_instance = buffer.create(1_073_741_824)-- 1GB buffer, you can set this to any value you want.
-- Offsets
local id_offset = 0 -- Global ID variable, it always rises.
local current_offset = 0 -- Current offset in memory.
-- Metatables
local uid_to_oid_vsize = {} -- A table that contains the metadata of all allocated objects.
-- Flags
local defragging = false -- Flag to make sure allocation doesn't happen during defragmentation.
-- Functions
-- Allocate an u8 to memory
-- This object can have the values 0<>255
function ManualMemoryManagement.alloc_u8(value: number): number
repeat task.wait() until defragging == false
if current_offset + 1 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writeu8(buffer_instance, start_offset, value)
current_offset += 1
uid_to_oid_vsize[id_offset] = {start_offset, 1, false, "u8"}
id_offset += 1
return id_offset - 1
end
-- Allocate an i8 to memory
-- This object can have the values -128<>127
function ManualMemoryManagement.alloc_i8(value: number): number
repeat task.wait() until defragging == false
if current_offset + 1 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writei8(buffer_instance, start_offset, value)
current_offset += 1
uid_to_oid_vsize[id_offset] = {start_offset, 1, false, "i8"}
id_offset += 1
return id_offset - 1
end
-- Allocate an u16 to memory
-- This object can have the values 0<>65,535
function ManualMemoryManagement.alloc_u16(value: number): number
repeat task.wait() until defragging == false
if current_offset + 2 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writeu16(buffer_instance, start_offset, value)
current_offset += 2
uid_to_oid_vsize[id_offset] = {start_offset, 2, false, "u16"}
id_offset += 1
return id_offset - 1
end
-- Allocate an i16 to memory
-- This object can have the values -32,768<>32,767
function ManualMemoryManagement.alloc_i16(value: number): number
repeat task.wait() until defragging == false
if current_offset + 2 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writei16(buffer_instance, start_offset, value)
current_offset += 2
uid_to_oid_vsize[id_offset] = {start_offset, 2, false, "i16"}
id_offset += 1
return id_offset - 1
end
-- Allocate an u32 to memory
-- This object can have the values 0<>4,294,967,295
function ManualMemoryManagement.alloc_u32(value: number): number
repeat task.wait() until defragging == false
if current_offset + 4 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writeu32(buffer_instance, start_offset, value)
current_offset += 4
uid_to_oid_vsize[id_offset] = {start_offset, 4, false, "u32"}
id_offset += 1
return id_offset - 1
end
-- Allocate an i32 to memory
-- This object can have the values -2,147,483,648<>2,147,483,647
function ManualMemoryManagement.alloc_i32(value: number): number
repeat task.wait() until defragging == false
if current_offset + 4 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writei32(buffer_instance, start_offset, value)
current_offset += 4
uid_to_oid_vsize[id_offset] = {start_offset, 4, false, "i32"}
id_offset += 1
return id_offset - 1
end
-- Allocate an f32 to memory
-- This object is a single-precision floating-point number
function ManualMemoryManagement.alloc_f32(value: number): number
repeat task.wait() until defragging == false
if current_offset + 4 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writef32(buffer_instance, start_offset, value)
current_offset += 4
uid_to_oid_vsize[id_offset] = {start_offset, 4, false, "f32"}
id_offset += 1
return id_offset - 1
end
-- Allocate an f64 to memory
-- This object is a double-precision floating-point number
function ManualMemoryManagement.alloc_f64(value: number): number
repeat task.wait() until defragging == false
if current_offset + 8 > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writef64(buffer_instance, start_offset, value)
current_offset += 8
uid_to_oid_vsize[id_offset] = {start_offset, 8, false, "f64"}
id_offset += 1
return id_offset - 1
end
-- Allocate a string to memory
-- This object can have any value, but it must be a string
function ManualMemoryManagement.alloc_str(value: string): number
repeat task.wait() until defragging == false
if current_offset + #value > 1_073_741_824 then
return -1
end
local start_offset = current_offset
buffer.writestring(buffer_instance, start_offset, value)
current_offset += #value
uid_to_oid_vsize[id_offset] = {start_offset, #value, true}
id_offset += 1
return id_offset - 1
end
-- Read a pointer from memory
-- This pointer can be any type of object, it will be returned as a number, string or nil
function ManualMemoryManagement.read(ptr): string | number | nil
repeat task.wait() until defragging == false
if uid_to_oid_vsize[ptr] then
if uid_to_oid_vsize[ptr][3] == true then
return buffer.readstring(buffer_instance, uid_to_oid_vsize[ptr][1], uid_to_oid_vsize[ptr][2])
else
if uid_to_oid_vsize[ptr][4] == "u8" then
return buffer.readu8(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "i8" then
return buffer.readi8(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "u16" then
return buffer.readu16(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "i16" then
return buffer.readi16(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "u32" then
return buffer.readu32(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "i32" then
return buffer.readi32(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "f32" then
return buffer.readf32(buffer_instance, uid_to_oid_vsize[ptr][1])
elseif uid_to_oid_vsize[ptr][4] == "f64" then
return buffer.readf64(buffer_instance, uid_to_oid_vsize[ptr][1])
end
end
else
return nil
end
end
-- Free an object from memory
-- This function will defrag the memory pool, eliminate the pointer from metatable and free the memory itself
function ManualMemoryManagement.free(uid)
if uid_to_oid_vsize[uid] then
defragging = true
task.spawn(function()
for k, v in pairs(uid_to_oid_vsize) do
if v[1] <= uid_to_oid_vsize[uid][1] then task.wait() continue end
if uid_to_oid_vsize[uid][3] == false then
if v[4] == "u8" then
buffer.writeu8(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readu8(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "i8" then
buffer.writei8(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readi8(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "u16" then
buffer.writeu16(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readu16(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "i16" then
buffer.writei16(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readi16(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "u32" then
buffer.writeu32(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readu32(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "i32" then
buffer.writei32(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readi32(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "f32" then
buffer.writef32(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readf32(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
elseif v[4] == "f64" then
buffer.writef64(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readf64(buffer_instance, v[1]))
v[1] -= uid_to_oid_vsize[uid][2]
end
else
buffer.writestring(buffer_instance, v[1] - uid_to_oid_vsize[uid][2], buffer.readstring(buffer_instance, v[1], v[2]))
v[1] -= uid_to_oid_vsize[uid][2]
end
task.wait()
end
current_offset -= uid_to_oid_vsize[uid][2]
uid_to_oid_vsize[uid] = nil
defragging = false
end)
else
return -1
end
end
function ManualMemoryManagement.getptrmeta(ptr: number)
return uid_to_oid_vsize[ptr]
end
return ManualMemoryManagement