Memory limit reached during state_entry method when there's plenty of memory left
in progress
Fizz Savira
I've been porting a set of three scripts to the LSL on luavm 2025 and have run into an unexpected memory limit issue.
As the script has grown by my enabling more of it by integrating the three scripts into one, the USED memory size has crossed the 64k boundary. This includes code and data, and because of a different bug that Harold Linden is aware of (code size greater than 64k triggers a constructor fault), I've been working to keep the code under 64k (just barely at this point).
Today I started getting these kinds of runtime errors:
PRIMA
Femme Elite v1.9 [script:body_lsl] Script run-time errornot enough memory
not enough memory
[C] function ListInsertList
[C] function ListReplaceList
lsl_script function _fupdate_link_alpha
lsl_script function _fchange_piece_shape
lsl_script function _e0/state_entry
By commenting out other code that is not used during the state_entry logic, the code runs. I'm guessing it's because there are checks in the list code called to make sure the lists are inside the 64k boundaries of days of yore.
I have some skid marks in my code and what I see are these two messages before the script fault occurs:
state_entry 0 used 61241 free 69831
state_entry2 1 used 66745 free 64327
The first one is the first statement in state_entry(). The second one is down a ways after I've initialized a bunch of my global variables. The third one I added to the code never runs because of the error shown above.
Log In
H
Harold Linden
Is this fixed for you on the beta grid? I believe the recent updates should have addressed it.
SuzannaLinn Resident
Harold Linden
I think that is not.
Testing with this: https://suzanna-linn.github.io/slua/files/test-memory-limit.txt, in Luau 2026-03-24.23471922914 on Aditi, uncommenting the last line throws a memory error.
H
Harold Linden
SuzannaLinn Resident Thanks! I'll have another look
Fizz Savira
Harold Linden It's not fixed in SLua at least, not sure about LSL on SLuaVM.
I uncommented out some code in my HUD and now it's blowing up again like this:
PRIMA
Femme Elite HUD v1.9 (ADD) slua [script:hud] Script run-time errornot enough memory
[C] function SetLinkPrimitiveParamsFast
lua_script:1078 function update_foot_indicators
lua_script:1890 function set_dark_mode
lua_script:2614 function main
lua_script:2663
Tapple Gao
Harold Linden The error still happens on lsl too. Here's a reproduction script. Tested on aditi Luau 2026-03-24.23471922914
Tapple Gao
SuzannaLinn Resident I noticed something weird about the script. Uncomment the last line, and you get
[3:59 PM] Object: Object [script:long function slua] Script run-time error
[3:59 PM] Object: not enough memory
[C] function lsl_print
lua_script:247
But, if you uncomment the last line, and then duplicate it, you get a different error:
[3:59 PM] Object: Object [script:long function slua] Script run-time error
[3:59 PM] Object: not enough memory
lua_script:1
The line number is different. Something similar happens in LSL. I noted it inside the comments in my lsl script above
Tapple Gao
Harold Linden just to make sure the memory limit works right for non-bytecode, here's a slua script right on the edge of running out of memory:
print(ll.GetUsedMemory(), ll.GetFreeMemory()) -- 2434 128638
local l = {}
for i = 1, 7936 do table.insert(l, i) end -- crash at 7937
print(ll.GetUsedMemory(), ll.GetFreeMemory()) -- 129442 1630
It's using nearly 128kb, as expected.
But for a lsl script on SLua:
default { state_entry() {
list l; integer i;
llOwnerSay((string)llGetUsedMemory() + " " + (string)llGetFreeMemory()); // 2524 128570
while(++i <= 4000) l += [i]; // crash at 4001
llOwnerSay((string)llGetUsedMemory() + " " + (string)llGetFreeMemory()); // 66521 554
}}
It crashes with
llGetUsedMemory()
being way too small, and llGetFreeMemory() + llGetUsedMemory()
are nowhere near 128kb. Incidentally:
- LSL Mono crashes at i = 3846
- LSL LSO crashes at i=473
I feel like LSL on SLua should do way better than LSL on Mono, unless it's due to integers being 32-bit in Mono and 64-bit in SLua. But then, why does SLua hit almost double?
H
Harold Linden
Tapple Gao
This is due to
list
s being immutable in LSL. When you do l += [something];
you're actually doing l = l + [something]
, and for a period both the modified l
and the original l
are on reachable until the assignment actually happens.As far as the "why" for expense, it's probably most helpful to look at https://github.com/secondlife/slua/blob/e609db7935f001045f9c137fc6b9383b74603198/VM/src/llsl.cpp#L596 and the generated bytecode for that script, as well as https://github.com/secondlife/slua/blob/main/VM/src/lgctraverse.cpp , everything that determines memory usage lives in there.
table.insert()
obviously has no such issues, because if a table ever needs to grow it can do so in-place.Tapple Gao
Harold Linden so,
- The discrepency between slua list size and lsl(slua) list size is due to list copying
- The discrepency between lsl(slua) and lsl(mono) is due to slua having both double the memory and double the overhead of storing numbers. I can test this by storing vectors instead, which are the same size on slua and mono (12 bytes)
I substituted number for vector in the above script and got:
- LSL on Slua crashes at 3999 vectors
- LSL on mono crashes at 2565 vectors
That's more what I was expecting
SuzannaLinn Resident
The same happens in SLua when using LL list functions:
local l = {}
for i = 1, 4009 do l = ll.ListInsertList(l, {i}, i) end -- crash at 4010
print(ll.GetUsedMemory(), ll.GetFreeMemory()) -- 66581 64491
It temporarily doubles the memory usage. An SLua array of 4,000 numbers (or vectors) uses 64,000 bytes.
The missing memory reported in the LSL/ Luau script (66521 and 554) is due to a reference to the original list remaining in the stack.
In SLua and VM Luau, the stack is sometimes not cleared until the script yields to the VM.
LL functions usually yield at the end, so calling the function twice works (LSL evaluates from right to left).
default { state_entry() {
list l; integer i;
while(++i <= 4003) l += [i]; // crash at 4004
llOwnerSay((string)llGetUsedMemory() + " " + (string)llGetFreeMemory() + " " + (string)llGetFreeMemory()); // 66540 64553 508
}}
Fizz Savira
I'm dead in the water again. My converted script that is now 100% SLua code has hit the same wall. Random functions that were working are now failing with not enough memory. If I comment out the new block of code that triggered this, that is not even being called, then it will finish initializing and then run fine.
Oddly though, the memory usage numbers are greater than 70k for memory used in both cases.
H
Harold Linden
marked this post as
in progress
Thanks for sending this in!
This should be fixed in the next release as part of the fix for the other issue you reported affecting LSL.
The issue is that we were double-counting bytecode size in the actual memory limiting logic, even though
ll.GetFreeMemory()
is what you'd expect.