-- Memory Profiler for CC:Tweaked / Opus OS -- Usage: memprofile [--watch] [--interval ] -- -- Shows current Lua memory usage with breakdown estimates. -- Use --watch to continuously monitor. -- Useful for detecting memory leaks and understanding overhead. local args = { ... } local watch = false local interval = 3 for i, arg in ipairs(args) do if arg == '--watch' or arg == '-w' then watch = true elseif arg == '--interval' or arg == '-i' then interval = tonumber(args[i + 1]) or 3 elseif arg == '--help' or arg == '-h' then print('Usage: memprofile [--watch] [--interval ]') print('') print('Options:') print(' --watch, -w Continuously monitor memory') print(' --interval, -i N Update interval in seconds (default: 3)') print(' --help, -h Show this help') return end end local term = _G.term local os = _G.os local function formatBytes(bytes) if bytes < 1024 then return string.format('%d B', bytes) elseif bytes < 1024 * 1024 then return string.format('%.1f KB', bytes / 1024) else return string.format('%.2f MB', bytes / (1024 * 1024)) end end local function countTable(t, seen) if type(t) ~= 'table' or seen[t] then return 0, 0 end seen[t] = true local entries = 0 local nested = 0 for k, v in pairs(t) do entries = entries + 1 if type(v) == 'table' then local e, n = countTable(v, seen) nested = nested + 1 + e entries = entries + n end if type(k) == 'table' then local e, n = countTable(k, seen) nested = nested + 1 + e entries = entries + n end end return entries, nested end local function getSnapshot() -- Force a full GC cycle to get accurate usage collectgarbage('collect') collectgarbage('collect') local memKB = collectgarbage('count') -- returns KB as float local snapshot = { totalKB = memKB, totalBytes = math.floor(memKB * 1024), timestamp = os.clock(), } -- Count entries in major global tables local seen = {} local globals = {} local interesting = { { name = '_G (globals)', tbl = _G }, { name = 'kernel', tbl = _G.kernel }, { name = 'network', tbl = _G.network }, { name = 'device', tbl = _G.device }, } for _, item in ipairs(interesting) do if type(item.tbl) == 'table' then local entries, nested = countTable(item.tbl, seen) table.insert(globals, { name = item.name, entries = entries, nested = nested, }) end end snapshot.globals = globals -- Count routines if kernel is available if _G.kernel and _G.kernel.routines then snapshot.routines = #_G.kernel.routines end -- Count loaded modules if package and package.loaded then local count = 0 for _ in pairs(package.loaded) do count = count + 1 end snapshot.loadedModules = count end return snapshot end local function printSnapshot(snap, prev) term.clear() term.setCursorPos(1, 1) local w = term.getSize() local sep = string.rep('-', w) term.setTextColor(colors.yellow) print('=== Memory Profile ===') term.setTextColor(colors.white) print('') -- Total memory local memStr = formatBytes(snap.totalBytes) local deltaStr = '' if prev then local delta = snap.totalBytes - prev.totalBytes if delta > 0 then deltaStr = string.format(' (+%s)', formatBytes(delta)) term.setTextColor(colors.red) elseif delta < 0 then deltaStr = string.format(' (-%s)', formatBytes(-delta)) term.setTextColor(colors.green) end end term.setTextColor(colors.white) print(string.format('Total Memory: %s%s', memStr, deltaStr)) print(string.format('Uptime: %.1fs', snap.timestamp)) print('') -- Table sizes term.setTextColor(colors.lightBlue) print('Global Tables:') term.setTextColor(colors.white) print(sep) print(string.format(' %-20s %8s %8s', 'Name', 'Entries', 'Nested')) print(sep) for _, g in ipairs(snap.globals) do print(string.format(' %-20s %8d %8d', g.name, g.entries, g.nested)) end print(sep) print('') -- Kernel info if snap.routines then term.setTextColor(colors.lightBlue) print('Kernel:') term.setTextColor(colors.white) print(string.format(' Active routines: %d', snap.routines)) end if snap.loadedModules then print(string.format(' Loaded modules: %d', snap.loadedModules)) end print('') -- CC:Tweaked limits term.setTextColor(colors.gray) print('Note: CC:Tweaked default memory limit is ~128MB per computer.') print('High memory usage may cause slowdowns or crashes.') if watch then print('') term.setTextColor(colors.yellow) print(string.format('Refreshing every %ds... (Ctrl+T to stop)', interval)) end end local function run() local prev = nil if watch then while true do local snap = getSnapshot() printSnapshot(snap, prev) prev = snap os.sleep(interval) end else local snap = getSnapshot() printSnapshot(snap, nil) end end run()